Merge branch 'ip7z:main' into main

This commit is contained in:
unxed 2025-01-21 21:39:42 +01:00 committed by GitHub
commit 299982cc8d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
167 changed files with 7264 additions and 2805 deletions

View file

@ -1,5 +1,5 @@
; LzFindOpt.asm -- ASM version of GetMatchesSpecN_2() function
; 2021-07-21: Igor Pavlov : Public domain
; 2024-06-18: Igor Pavlov : Public domain
;
ifndef x64
@ -11,10 +11,31 @@ include 7zAsm.asm
MY_ASM_START
_TEXT$LZFINDOPT SEGMENT ALIGN(64) 'CODE'
ifndef Z7_LZ_FIND_OPT_ASM_USE_SEGMENT
if (IS_LINUX gt 0)
Z7_LZ_FIND_OPT_ASM_USE_SEGMENT equ 1
else
Z7_LZ_FIND_OPT_ASM_USE_SEGMENT equ 1
endif
endif
ifdef Z7_LZ_FIND_OPT_ASM_USE_SEGMENT
_TEXT$LZFINDOPT SEGMENT ALIGN(64) 'CODE'
MY_ALIGN macro num:req
align num
; align 16
endm
else
MY_ALIGN macro num:req
; We expect that ".text" is aligned for 16-bytes.
; So we don't need large alignment inside our function.
align 16
endm
endif
MY_ALIGN_16 macro
MY_ALIGN 16
endm
MY_ALIGN_32 macro
@ -136,7 +157,11 @@ COPY_VAR_64 macro dest_var, src_var
endm
ifdef Z7_LZ_FIND_OPT_ASM_USE_SEGMENT
; MY_ALIGN_64
else
MY_ALIGN_16
endif
MY_PROC GetMatchesSpecN_2, 13
MY_PUSH_PRESERVED_ABI_REGS
mov r0, RSP
@ -508,6 +533,8 @@ fin:
MY_POP_PRESERVED_ABI_REGS
MY_ENDP
ifdef Z7_LZ_FIND_OPT_ASM_USE_SEGMENT
_TEXT$LZFINDOPT ENDS
endif
end

View file

@ -1,5 +1,5 @@
; LzmaDecOpt.asm -- ASM version of LzmaDec_DecodeReal_3() function
; 2021-02-23: Igor Pavlov : Public domain
; 2024-06-18: Igor Pavlov : Public domain
;
; 3 - is the code compatibility version of LzmaDec_DecodeReal_*()
; function for check at link time.
@ -17,11 +17,41 @@ include 7zAsm.asm
MY_ASM_START
_TEXT$LZMADECOPT SEGMENT ALIGN(64) 'CODE'
; if Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT is defined, we use additional SEGMENT with 64-byte alignment.
; if Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT is not defined, we use default SEGMENT (where default 16-byte alignment of segment is expected).
; The performance is almost identical in our tests.
; But the performance can depend from position of lzmadec code inside instruction cache
; or micro-op cache line (depending from low address bits in 32-byte/64-byte cache lines).
; And 64-byte alignment provides a more consistent speed regardless
; of the code's position in the executable.
; But also it's possible that code without Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT can be
; slightly faster than 64-bytes aligned code in some cases, if offset of lzmadec
; code in 64-byte block after compilation provides better speed by some reason.
; Note that Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT adds an extra section to the ELF file.
; If you don't want to get that extra section, do not define Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT.
ifndef Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT
if (IS_LINUX gt 0)
Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT equ 1
else
Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT equ 1
endif
endif
ifdef Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT
_TEXT$LZMADECOPT SEGMENT ALIGN(64) 'CODE'
MY_ALIGN macro num:req
align num
; align 16
endm
else
MY_ALIGN macro num:req
; We expect that ".text" is aligned for 16-bytes.
; So we don't need large alignment inside out function.
align 16
endm
endif
MY_ALIGN_16 macro
MY_ALIGN 16
@ -610,7 +640,11 @@ PARAM_lzma equ REG_ABI_PARAM_0
PARAM_limit equ REG_ABI_PARAM_1
PARAM_bufLimit equ REG_ABI_PARAM_2
ifdef Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT
; MY_ALIGN_64
else
MY_ALIGN_16
endif
MY_PROC LzmaDec_DecodeReal_3, 3
MY_PUSH_PRESERVED_ABI_REGS
@ -1298,6 +1332,8 @@ fin:
MY_POP_PRESERVED_ABI_REGS
MY_ENDP
ifdef Z7_LZMA_DEC_OPT_ASM_USE_SEGMENT
_TEXT$LZMADECOPT ENDS
endif
end

View file

@ -1,5 +1,5 @@
; Sha1Opt.asm -- SHA-1 optimized code for SHA-1 x86 hardware instructions
; 2021-03-10 : Igor Pavlov : Public domain
; 2024-06-16 : Igor Pavlov : Public domain
include 7zAsm.asm
@ -20,7 +20,7 @@ MY_ASM_START
CONST SEGMENT
CONST SEGMENT READONLY
align 16
Reverse_Endian_Mask db 15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0

View file

@ -1,5 +1,5 @@
; Sha256Opt.asm -- SHA-256 optimized code for SHA-256 x86 hardware instructions
; 2022-04-17 : Igor Pavlov : Public domain
; 2024-06-16 : Igor Pavlov : Public domain
include 7zAsm.asm
@ -20,7 +20,7 @@ endif
EXTRN K_CONST:xmmword
@
CONST SEGMENT
CONST SEGMENT READONLY
align 16
Reverse_Endian_Mask db 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12

View file

@ -1,5 +1,5 @@
/* 7zDec.c -- Decoding from 7z folder
2024-03-01 : Igor Pavlov : Public domain */
: Igor Pavlov : Public domain */
#include "Precomp.h"
@ -312,8 +312,9 @@ static BoolInt IS_MAIN_METHOD(UInt32 m)
case k_PPMD:
#endif
return True;
default:
return False;
}
return False;
}
static BoolInt IS_SUPPORTED_CODER(const CSzCoderInfo *c)

View file

@ -1,7 +1,7 @@
#define MY_VER_MAJOR 24
#define MY_VER_MINOR 06
#define MY_VER_MINOR 9
#define MY_VER_BUILD 0
#define MY_VERSION_NUMBERS "24.06"
#define MY_VERSION_NUMBERS "24.09"
#define MY_VERSION MY_VERSION_NUMBERS
#ifdef MY_CPU_NAME
@ -10,7 +10,7 @@
#define MY_VERSION_CPU MY_VERSION
#endif
#define MY_DATE "2024-05-26"
#define MY_DATE "2024-11-29"
#undef MY_COPYRIGHT
#undef MY_VERSION_COPYRIGHT_DATE
#define MY_AUTHOR_NAME "Igor Pavlov"

View file

@ -1,5 +1,5 @@
/* AesOpt.c -- AES optimized code for x86 AES hardware instructions
2024-03-01 : Igor Pavlov : Public domain */
Igor Pavlov : Public domain */
#include "Precomp.h"
@ -80,19 +80,39 @@ AES_FUNC_START (name)
#define MM_XOR( dest, src) MM_OP(_mm_xor_si128, dest, src)
#if 1
// use aligned SSE load/store for data.
// It is required for our Aes functions, that data is aligned for 16-bytes.
// So we can use this branch of code.
// and compiler can use fused load-op SSE instructions:
// xorps xmm0, XMMWORD PTR [rdx]
#define LOAD_128(pp) (*(__m128i *)(void *)(pp))
#define STORE_128(pp, _v) *(__m128i *)(void *)(pp) = _v
// use aligned SSE load/store for data. Alternative code with direct access
// #define LOAD_128(pp) _mm_load_si128(pp)
// #define STORE_128(pp, _v) _mm_store_si128(pp, _v)
#else
// use unaligned load/store for data: movdqu XMMWORD PTR [rdx]
#define LOAD_128(pp) _mm_loadu_si128(pp)
#define STORE_128(pp, _v) _mm_storeu_si128(pp, _v)
#endif
AES_FUNC_START2 (AesCbc_Encode_HW)
{
if (numBlocks == 0)
return;
{
__m128i *p = (__m128i *)(void *)ivAes;
__m128i *data = (__m128i *)(void *)data8;
__m128i m = *p;
const __m128i k0 = p[2];
const __m128i k1 = p[3];
const UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1;
for (; numBlocks != 0; numBlocks--, data++)
do
{
UInt32 r = numRounds2;
const __m128i *w = p + 4;
__m128i temp = *data;
__m128i temp = LOAD_128(data);
MM_XOR (temp, k0)
MM_XOR (m, temp)
MM_OP_m (_mm_aesenc_si128, k1)
@ -104,9 +124,12 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
}
while (--r);
MM_OP_m (_mm_aesenclast_si128, w[0])
*data = m;
STORE_128(data, m);
data++;
}
while (--numBlocks);
*p = m;
}
}
@ -139,12 +162,12 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
#define WOP(op) op (m0, 0) WOP_M1(op)
#define DECLARE_VAR(reg, ii) __m128i reg;
#define LOAD_data( reg, ii) reg = data[ii];
#define STORE_data( reg, ii) data[ii] = reg;
#define LOAD_data_ii(ii) LOAD_128(data + (ii))
#define LOAD_data( reg, ii) reg = LOAD_data_ii(ii);
#define STORE_data( reg, ii) STORE_128(data + (ii), reg);
#if (NUM_WAYS > 1)
#define XOR_data_M1(reg, ii) MM_XOR (reg, data[ii- 1])
#define XOR_data_M1(reg, ii) MM_XOR (reg, LOAD_128(data + (ii- 1)))
#endif
#define MM_OP_key(op, reg) MM_OP(op, reg, key);
@ -156,25 +179,22 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
#define AES_XOR( reg, ii) MM_OP_key (_mm_xor_si128, reg)
#define CTR_START(reg, ii) MM_OP (_mm_add_epi64, ctr, one) reg = ctr;
#define CTR_END( reg, ii) MM_XOR (data[ii], reg)
#define CTR_END( reg, ii) STORE_128(data + (ii), _mm_xor_si128(reg, \
LOAD_128 (data + (ii))));
#define WOP_KEY(op, n) { \
const __m128i key = w[n]; \
WOP(op); }
WOP(op) }
#define WIDE_LOOP_START \
dataEnd = data + numBlocks; \
if (numBlocks >= NUM_WAYS) \
{ dataEnd -= NUM_WAYS; do { \
#define WIDE_LOOP_END \
data += NUM_WAYS; \
} while (data <= dataEnd); \
dataEnd += NUM_WAYS; } \
#define SINGLE_LOOP \
for (; data < dataEnd; data++)
@ -184,54 +204,73 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
#define AVX_XOR(dest, src) MM_OP(_mm256_xor_si256, dest, src)
#define AVX_DECLARE_VAR(reg, ii) __m256i reg;
#define AVX_LOAD_data( reg, ii) reg = ((const __m256i *)(const void *)data)[ii];
#define AVX_STORE_data( reg, ii) ((__m256i *)(void *)data)[ii] = reg;
#if 1
// use unaligned AVX load/store for data.
// It is required for our Aes functions, that data is aligned for 16-bytes.
// But we need 32-bytes reading.
// So we use intrinsics for unaligned AVX load/store.
// notes for _mm256_storeu_si256:
// msvc2022: uses vmovdqu and keeps the order of instruction sequence.
// new gcc11 uses vmovdqu
// old gcc9 could use pair of instructions:
// vmovups %xmm7, -224(%rax)
// vextracti128 $0x1, %ymm7, -208(%rax)
#define AVX_LOAD(p) _mm256_loadu_si256((const __m256i *)(const void *)(p))
#define AVX_STORE(p, _v) _mm256_storeu_si256((__m256i *)(void *)(p), _v);
#else
// use aligned AVX load/store for data.
// for debug: we can use this branch, if we are sure that data is aligned for 32-bytes.
// msvc2022 uses vmovdqu still
// gcc uses vmovdqa (that requires 32-bytes alignment)
#define AVX_LOAD(p) (*(const __m256i *)(const void *)(p))
#define AVX_STORE(p, _v) (*(__m256i *)(void *)(p)) = _v;
#endif
#define AVX_LOAD_data( reg, ii) reg = AVX_LOAD((const __m256i *)(const void *)data + (ii));
#define AVX_STORE_data( reg, ii) AVX_STORE((__m256i *)(void *)data + (ii), reg)
/*
AVX_XOR_data_M1() needs unaligned memory load
if (we don't use _mm256_loadu_si256() here)
{
Most compilers with enabled optimizations generate fused AVX (LOAD + OP)
instruction that can load unaligned data.
But GCC and CLANG without -O2 or -O1 optimizations can generate separated
LOAD-ALIGNED (vmovdqa) instruction that will fail on execution.
}
Note: some compilers generate more instructions, if we use _mm256_loadu_si256() here.
v23.02: we use _mm256_loadu_si256() here, because we need compatibility with any compiler.
AVX_XOR_data_M1() needs unaligned memory load, even if (data)
is aligned for 256-bits, because we read 32-bytes chunk that
crosses (data) position: from (data - 16bytes) to (data + 16bytes).
*/
#define AVX_XOR_data_M1(reg, ii) AVX_XOR (reg, _mm256_loadu_si256(&(((const __m256i *)(const void *)(data - 1))[ii])))
// for debug only: the following code will fail on execution, if compiled by some compilers:
// #define AVX_XOR_data_M1(reg, ii) AVX_XOR (reg, (((const __m256i *)(const void *)(data - 1))[ii]))
#define AVX_XOR_data_M1(reg, ii) AVX_XOR (reg, _mm256_loadu_si256((const __m256i *)(const void *)(data - 1) + (ii)))
#define AVX_AES_DEC( reg, ii) MM_OP_key (_mm256_aesdec_epi128, reg)
#define AVX_AES_DEC_LAST( reg, ii) MM_OP_key (_mm256_aesdeclast_epi128, reg)
#define AVX_AES_ENC( reg, ii) MM_OP_key (_mm256_aesenc_epi128, reg)
#define AVX_AES_ENC_LAST( reg, ii) MM_OP_key (_mm256_aesenclast_epi128, reg)
#define AVX_AES_XOR( reg, ii) MM_OP_key (_mm256_xor_si256, reg)
#define AVX_CTR_START(reg, ii) MM_OP (_mm256_add_epi64, ctr2, two) reg = _mm256_xor_si256(ctr2, key);
#define AVX_CTR_END( reg, ii) AVX_XOR (((__m256i *)(void *)data)[ii], reg)
#define AVX_CTR_START(reg, ii) \
MM_OP (_mm256_add_epi64, ctr2, two) \
reg = _mm256_xor_si256(ctr2, key);
#define AVX_CTR_END(reg, ii) \
AVX_STORE((__m256i *)(void *)data + (ii), _mm256_xor_si256(reg, \
AVX_LOAD ((__m256i *)(void *)data + (ii))));
#define AVX_WOP_KEY(op, n) { \
const __m256i key = w[n]; \
WOP(op); }
WOP(op) }
#define NUM_AES_KEYS_MAX 15
#define WIDE_LOOP_START_AVX(OP) \
dataEnd = data + numBlocks; \
if (numBlocks >= NUM_WAYS * 2) \
{ __m256i keys[NUM_AES_KEYS_MAX]; \
UInt32 ii; \
OP \
for (ii = 0; ii < numRounds; ii++) \
keys[ii] = _mm256_broadcastsi128_si256(p[ii]); \
dataEnd -= NUM_WAYS * 2; do { \
{ __m256i keys[NUM_AES_KEYS_MAX]; \
OP \
{ UInt32 ii; for (ii = 0; ii < numRounds; ii++) \
keys[ii] = _mm256_broadcastsi128_si256(p[ii]); } \
dataEnd -= NUM_WAYS * 2; \
do { \
#define WIDE_LOOP_END_AVX(OP) \
data += NUM_WAYS * 2; \
} while (data <= dataEnd); \
dataEnd += NUM_WAYS * 2; \
OP \
_mm256_zeroupper(); \
data += NUM_WAYS * 2; \
} while (data <= dataEnd); \
dataEnd += NUM_WAYS * 2; \
OP \
_mm256_zeroupper(); \
} \
/* MSVC for x86: If we don't call _mm256_zeroupper(), and -arch:IA32 is not specified,
@ -246,21 +285,20 @@ AES_FUNC_START2 (AesCbc_Decode_HW)
__m128i *p = (__m128i *)(void *)ivAes;
__m128i *data = (__m128i *)(void *)data8;
__m128i iv = *p;
const __m128i *wStart = p + *(const UInt32 *)(p + 1) * 2 + 2 - 1;
const __m128i * const wStart = p + (size_t)*(const UInt32 *)(p + 1) * 2 + 2 - 1;
const __m128i *dataEnd;
p += 2;
WIDE_LOOP_START
{
const __m128i *w = wStart;
WOP (DECLARE_VAR)
WOP (LOAD_data)
WOP_KEY (AES_XOR, 1)
do
{
WOP_KEY (AES_DEC, 0)
w--;
}
while (w != p);
@ -268,7 +306,7 @@ AES_FUNC_START2 (AesCbc_Decode_HW)
MM_XOR (m0, iv)
WOP_M1 (XOR_data_M1)
iv = data[NUM_WAYS - 1];
LOAD_data(iv, NUM_WAYS - 1)
WOP (STORE_data)
}
WIDE_LOOP_END
@ -276,7 +314,8 @@ AES_FUNC_START2 (AesCbc_Decode_HW)
SINGLE_LOOP
{
const __m128i *w = wStart - 1;
__m128i m = _mm_xor_si128 (w[2], *data);
__m128i m = _mm_xor_si128 (w[2], LOAD_data_ii(0));
do
{
MM_OP_m (_mm_aesdec_si128, w[1])
@ -286,10 +325,9 @@ AES_FUNC_START2 (AesCbc_Decode_HW)
while (w != p);
MM_OP_m (_mm_aesdec_si128, w[1])
MM_OP_m (_mm_aesdeclast_si128, w[0])
MM_XOR (m, iv)
iv = *data;
*data = m;
LOAD_data(iv, 0)
STORE_data(m, 0)
}
p[-2] = iv;
@ -301,9 +339,9 @@ AES_FUNC_START2 (AesCtr_Code_HW)
__m128i *p = (__m128i *)(void *)ivAes;
__m128i *data = (__m128i *)(void *)data8;
__m128i ctr = *p;
UInt32 numRoundsMinus2 = *(const UInt32 *)(p + 1) * 2 - 1;
const UInt32 numRoundsMinus2 = *(const UInt32 *)(p + 1) * 2 - 1;
const __m128i *dataEnd;
__m128i one = _mm_cvtsi32_si128(1);
const __m128i one = _mm_cvtsi32_si128(1);
p += 2;
@ -322,7 +360,6 @@ AES_FUNC_START2 (AesCtr_Code_HW)
}
while (--r);
WOP_KEY (AES_ENC_LAST, 0)
WOP (CTR_END)
}
WIDE_LOOP_END
@ -344,7 +381,7 @@ AES_FUNC_START2 (AesCtr_Code_HW)
while (--numRounds2);
MM_OP_m (_mm_aesenc_si128, w[0])
MM_OP_m (_mm_aesenclast_si128, w[1])
MM_XOR (*data, m)
CTR_END (m, 0)
}
p[-2] = ctr;
@ -421,7 +458,7 @@ VAES_FUNC_START2 (AesCbc_Decode_HW_256)
__m128i *data = (__m128i *)(void *)data8;
__m128i iv = *p;
const __m128i *dataEnd;
UInt32 numRounds = *(const UInt32 *)(p + 1) * 2 + 1;
const UInt32 numRounds = *(const UInt32 *)(p + 1) * 2 + 1;
p += 2;
WIDE_LOOP_START_AVX(;)
@ -440,17 +477,17 @@ VAES_FUNC_START2 (AesCbc_Decode_HW_256)
while (w != keys);
AVX_WOP_KEY (AVX_AES_DEC_LAST, 0)
AVX_XOR (m0, _mm256_setr_m128i(iv, data[0]))
AVX_XOR (m0, _mm256_setr_m128i(iv, LOAD_data_ii(0)))
WOP_M1 (AVX_XOR_data_M1)
iv = data[NUM_WAYS * 2 - 1];
LOAD_data (iv, NUM_WAYS * 2 - 1)
WOP (AVX_STORE_data)
}
WIDE_LOOP_END_AVX(;)
SINGLE_LOOP
{
const __m128i *w = p + *(const UInt32 *)(p + 1 - 2) * 2 + 1 - 3;
__m128i m = _mm_xor_si128 (w[2], *data);
const __m128i *w = p - 2 + (size_t)*(const UInt32 *)(p + 1 - 2) * 2;
__m128i m = _mm_xor_si128 (w[2], LOAD_data_ii(0));
do
{
MM_OP_m (_mm_aesdec_si128, w[1])
@ -462,8 +499,8 @@ VAES_FUNC_START2 (AesCbc_Decode_HW_256)
MM_OP_m (_mm_aesdeclast_si128, w[0])
MM_XOR (m, iv)
iv = *data;
*data = m;
LOAD_data(iv, 0)
STORE_data(m, 0)
}
p[-2] = iv;
@ -493,9 +530,9 @@ VAES_FUNC_START2 (AesCtr_Code_HW_256)
__m128i *p = (__m128i *)(void *)ivAes;
__m128i *data = (__m128i *)(void *)data8;
__m128i ctr = *p;
UInt32 numRounds = *(const UInt32 *)(p + 1) * 2 + 1;
const UInt32 numRounds = *(const UInt32 *)(p + 1) * 2 + 1;
const __m128i *dataEnd;
__m128i one = _mm_cvtsi32_si128(1);
const __m128i one = _mm_cvtsi32_si128(1);
__m256i ctr2, two;
p += 2;
@ -536,7 +573,7 @@ VAES_FUNC_START2 (AesCtr_Code_HW_256)
while (--numRounds2);
MM_OP_m (_mm_aesenc_si128, w[0])
MM_OP_m (_mm_aesenclast_si128, w[1])
MM_XOR (*data, m)
CTR_END (m, 0)
}
p[-2] = ctr;
@ -731,9 +768,14 @@ AES_FUNC_START (name)
AES_FUNC_START2 (AesCbc_Encode_HW)
{
v128 * const p = (v128*)(void*)ivAes;
v128 *data = (v128*)(void*)data8;
if (numBlocks == 0)
return;
{
v128 * const p = (v128 *)(void *)ivAes;
v128 *data = (v128 *)(void *)data8;
v128 m = *p;
const UInt32 numRounds2 = *(const UInt32 *)(p + 1);
const v128 *w = p + (size_t)numRounds2 * 2;
const v128 k0 = p[2];
const v128 k1 = p[3];
const v128 k2 = p[4];
@ -744,11 +786,14 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
const v128 k7 = p[9];
const v128 k8 = p[10];
const v128 k9 = p[11];
const UInt32 numRounds2 = *(const UInt32 *)(p + 1);
const v128 *w = p + ((size_t)numRounds2 * 2);
const v128 k_z4 = w[-2];
const v128 k_z3 = w[-1];
const v128 k_z2 = w[0];
const v128 k_z1 = w[1];
const v128 k_z0 = w[2];
for (; numBlocks != 0; numBlocks--, data++)
// we don't use optimization veorq_u8(*data, k_z0) that can reduce one cycle,
// because gcc/clang compilers are not good for that optimization.
do
{
MM_XOR_m (*data)
AES_E_MC_m (k0)
@ -757,24 +802,26 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
AES_E_MC_m (k3)
AES_E_MC_m (k4)
AES_E_MC_m (k5)
AES_E_MC_m (k6)
AES_E_MC_m (k7)
AES_E_MC_m (k8)
if (numRounds2 >= 6)
{
AES_E_MC_m (k9)
AES_E_MC_m (p[12])
AES_E_MC_m (k6)
AES_E_MC_m (k7)
if (numRounds2 != 6)
{
AES_E_MC_m (p[13])
AES_E_MC_m (p[14])
AES_E_MC_m (k8)
AES_E_MC_m (k9)
}
}
AES_E_m (k_z1)
MM_XOR_m (k_z0)
*data = m;
AES_E_MC_m (k_z4)
AES_E_MC_m (k_z3)
AES_E_MC_m (k_z2)
AES_E_m (k_z1)
MM_XOR_m (k_z0)
*data++ = m;
}
while (--numBlocks);
*p = m;
}
}
@ -834,10 +881,10 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
AES_FUNC_START2 (AesCbc_Decode_HW)
{
v128 *p = (v128*)(void*)ivAes;
v128 *data = (v128*)(void*)data8;
v128 *p = (v128 *)(void *)ivAes;
v128 *data = (v128 *)(void *)data8;
v128 iv = *p;
const v128 *wStart = p + ((size_t)*(const UInt32 *)(p + 1)) * 2;
const v128 * const wStart = p + (size_t)*(const UInt32 *)(p + 1) * 2;
const v128 *dataEnd;
p += 2;
@ -858,7 +905,7 @@ AES_FUNC_START2 (AesCbc_Decode_HW)
WOP_KEY (AES_XOR, 0)
MM_XOR (m0, iv)
WOP_M1 (XOR_data_M1)
iv = data[NUM_WAYS - 1];
LOAD_data(iv, NUM_WAYS - 1)
WOP (STORE_data)
}
WIDE_LOOP_END
@ -866,7 +913,7 @@ AES_FUNC_START2 (AesCbc_Decode_HW)
SINGLE_LOOP
{
const v128 *w = wStart;
v128 m = *data;
v128 m; LOAD_data(m, 0)
AES_D_IMC_m (w[2])
do
{
@ -878,8 +925,8 @@ AES_FUNC_START2 (AesCbc_Decode_HW)
AES_D_m (w[1])
MM_XOR_m (w[0])
MM_XOR_m (iv)
iv = *data;
*data = m;
LOAD_data(iv, 0)
STORE_data(m, 0)
}
p[-2] = iv;
@ -888,19 +935,17 @@ AES_FUNC_START2 (AesCbc_Decode_HW)
AES_FUNC_START2 (AesCtr_Code_HW)
{
v128 *p = (v128*)(void*)ivAes;
v128 *data = (v128*)(void*)data8;
v128 *p = (v128 *)(void *)ivAes;
v128 *data = (v128 *)(void *)data8;
uint64x2_t ctr = vreinterpretq_u64_u8(*p);
const v128 *wEnd = p + ((size_t)*(const UInt32 *)(p + 1)) * 2;
const v128 * const wEnd = p + (size_t)*(const UInt32 *)(p + 1) * 2;
const v128 *dataEnd;
uint64x2_t one = vdupq_n_u64(0);
// the bug in clang:
// __builtin_neon_vsetq_lane_i64(__s0, (int8x16_t)__s1, __p2);
#if defined(__clang__) && (__clang_major__ <= 9)
#pragma GCC diagnostic ignored "-Wvector-conversion"
#endif
one = vsetq_lane_u64(1, one, 0);
const uint64x2_t one = vsetq_lane_u64(1, vdupq_n_u64(0), 0);
p += 2;
WIDE_LOOP_START

View file

@ -1,5 +1,5 @@
/* CpuArch.c -- CPU specific code
2024-05-18 : Igor Pavlov : Public domain */
Igor Pavlov : Public domain */
#include "Precomp.h"
@ -17,7 +17,7 @@
/*
cpuid instruction supports (subFunction) parameter in ECX,
that is used only with some specific (function) parameter values.
But we always use only (subFunction==0).
most functions use only (subFunction==0).
*/
/*
__cpuid(): MSVC and GCC/CLANG use same function/macro name
@ -49,43 +49,49 @@
#if defined(MY_CPU_AMD64) && defined(__PIC__) \
&& ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__))
#define x86_cpuid_MACRO(p, func) { \
/* "=&r" selects free register. It can select even rbx, if that register is free.
"=&D" for (RDI) also works, but the code can be larger with "=&D"
"2"(subFun) : 2 is (zero-based) index in the output constraint list "=c" (ECX). */
#define x86_cpuid_MACRO_2(p, func, subFunc) { \
__asm__ __volatile__ ( \
ASM_LN "mov %%rbx, %q1" \
ASM_LN "cpuid" \
ASM_LN "xchg %%rbx, %q1" \
: "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); }
/* "=&r" selects free register. It can select even rbx, if that register is free.
"=&D" for (RDI) also works, but the code can be larger with "=&D"
"2"(0) means (subFunction = 0),
2 is (zero-based) index in the output constraint list "=c" (ECX). */
: "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(subFunc)); }
#elif defined(MY_CPU_X86) && defined(__PIC__) \
&& ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__))
#define x86_cpuid_MACRO(p, func) { \
#define x86_cpuid_MACRO_2(p, func, subFunc) { \
__asm__ __volatile__ ( \
ASM_LN "mov %%ebx, %k1" \
ASM_LN "cpuid" \
ASM_LN "xchg %%ebx, %k1" \
: "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); }
: "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(subFunc)); }
#else
#define x86_cpuid_MACRO(p, func) { \
#define x86_cpuid_MACRO_2(p, func, subFunc) { \
__asm__ __volatile__ ( \
ASM_LN "cpuid" \
: "=a" ((p)[0]), "=b" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); }
: "=a" ((p)[0]), "=b" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(subFunc)); }
#endif
#define x86_cpuid_MACRO(p, func) x86_cpuid_MACRO_2(p, func, 0)
void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
{
x86_cpuid_MACRO(p, func)
}
static
void Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc)
{
x86_cpuid_MACRO_2(p, func, subFunc)
}
Z7_NO_INLINE
UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)
@ -205,11 +211,39 @@ void __declspec(naked) Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
__asm ret 0
}
static
void __declspec(naked) Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc)
{
UNUSED_VAR(p)
UNUSED_VAR(func)
UNUSED_VAR(subFunc)
__asm push ebx
__asm push edi
__asm mov edi, ecx // p
__asm mov eax, edx // func
__asm mov ecx, [esp + 12] // subFunc
__asm cpuid
__asm mov [edi ], eax
__asm mov [edi + 4], ebx
__asm mov [edi + 8], ecx
__asm mov [edi + 12], edx
__asm pop edi
__asm pop ebx
__asm ret 4
}
#else // MY_CPU_AMD64
#if _MSC_VER >= 1600
#include <intrin.h>
#define MY_cpuidex __cpuidex
static
void Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc)
{
__cpuidex((int *)p, func, subFunc);
}
#else
/*
__cpuid (func == (0 or 7)) requires subfunction number in ECX.
@ -219,7 +253,7 @@ void __declspec(naked) Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
We still can use __cpuid for low (func) values that don't require ECX,
but __cpuid() in old MSVC will be incorrect for some func values: (func == 7).
So here we use the hack for old MSVC to send (subFunction) in ECX register to cpuid instruction,
where ECX value is first parameter for FASTCALL / NO_INLINE func,
where ECX value is first parameter for FASTCALL / NO_INLINE func.
So the caller of MY_cpuidex_HACK() sets ECX as subFunction, and
old MSVC for __cpuid() doesn't change ECX and cpuid instruction gets (subFunction) value.
@ -233,6 +267,11 @@ Z7_NO_INLINE void Z7_FASTCALL MY_cpuidex_HACK(Int32 subFunction, Int32 func, Int
}
#define MY_cpuidex(info, func, func2) MY_cpuidex_HACK(func2, func, info)
#pragma message("======== MY_cpuidex_HACK WAS USED ========")
static
void Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc)
{
MY_cpuidex_HACK(subFunc, func, (Int32 *)p);
}
#endif // _MSC_VER >= 1600
#if !defined(MY_CPU_AMD64)
@ -445,6 +484,23 @@ BoolInt CPU_IsSupported_SHA(void)
}
}
BoolInt CPU_IsSupported_SHA512(void)
{
if (!CPU_IsSupported_AVX2()) return False; // maybe CPU_IsSupported_AVX() is enough here
if (z7_x86_cpuid_GetMaxFunc() < 7)
return False;
{
UInt32 d[4];
z7_x86_cpuid_subFunc(d, 7, 0);
if (d[0] < 1) // d[0] - is max supported subleaf value
return False;
z7_x86_cpuid_subFunc(d, 7, 1);
return (BoolInt)(d[0]) & 1;
}
}
/*
MSVC: _xgetbv() intrinsic is available since VS2010SP1.
MSVC also defines (_XCR_XFEATURE_ENABLED_MASK) macro in
@ -776,6 +832,18 @@ BoolInt CPU_IsSupported_NEON(void)
return z7_sysctlbyname_Get_BoolInt("hw.optional.neon");
}
BoolInt CPU_IsSupported_SHA512(void)
{
return z7_sysctlbyname_Get_BoolInt("hw.optional.armv8_2_sha512");
}
/*
BoolInt CPU_IsSupported_SHA3(void)
{
return z7_sysctlbyname_Get_BoolInt("hw.optional.armv8_2_sha3");
}
*/
#ifdef MY_CPU_ARM64
#define APPLE_CRYPTO_SUPPORT_VAL 1
#else
@ -848,7 +916,11 @@ static unsigned long MY_getauxval(int aux)
#define MY_HWCAP_CHECK_FUNC(name) \
BoolInt CPU_IsSupported_ ## name(void) { return 0; }
#if defined(__ARM_NEON)
BoolInt CPU_IsSupported_NEON(void) { return True; }
#else
MY_HWCAP_CHECK_FUNC(NEON)
#endif
#endif // USE_HWCAP
@ -856,6 +928,19 @@ MY_HWCAP_CHECK_FUNC (CRC32)
MY_HWCAP_CHECK_FUNC (SHA1)
MY_HWCAP_CHECK_FUNC (SHA2)
MY_HWCAP_CHECK_FUNC (AES)
#ifdef MY_CPU_ARM64
// <hwcap.h> supports HWCAP_SHA512 and HWCAP_SHA3 since 2017.
// we define them here, if they are not defined
#ifndef HWCAP_SHA3
// #define HWCAP_SHA3 (1 << 17)
#endif
#ifndef HWCAP_SHA512
// #pragma message("=== HWCAP_SHA512 define === ")
#define HWCAP_SHA512 (1 << 21)
#endif
MY_HWCAP_CHECK_FUNC (SHA512)
// MY_HWCAP_CHECK_FUNC (SHA3)
#endif
#endif // __APPLE__
#endif // _WIN32

View file

@ -1,5 +1,5 @@
/* CpuArch.h -- CPU specific code
2024-05-18 : Igor Pavlov : Public domain */
Igor Pavlov : Public domain */
#ifndef ZIP7_INC_CPU_ARCH_H
#define ZIP7_INC_CPU_ARCH_H
@ -509,11 +509,19 @@ problem-4 : performace:
#if defined(MY_CPU_LE_UNALIGN) && defined(Z7_CPU_FAST_BSWAP_SUPPORTED)
#if 0
// Z7_BSWAP16 can be slow for x86-msvc
#define GetBe16_to32(p) (Z7_BSWAP16 (*(const UInt16 *)(const void *)(p)))
#else
#define GetBe16_to32(p) (Z7_BSWAP32 (*(const UInt16 *)(const void *)(p)) >> 16)
#endif
#define GetBe32(p) Z7_BSWAP32 (*(const UInt32 *)(const void *)(p))
#define SetBe32(p, v) { (*(UInt32 *)(void *)(p)) = Z7_BSWAP32(v); }
#if defined(MY_CPU_LE_UNALIGN_64)
#define GetBe64(p) Z7_BSWAP64 (*(const UInt64 *)(const void *)(p))
#define SetBe64(p, v) { (*(UInt64 *)(void *)(p)) = Z7_BSWAP64(v); }
#endif
#else
@ -536,11 +544,27 @@ problem-4 : performace:
#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
#endif
#ifndef SetBe64
#define SetBe64(p, v) { Byte *_ppp_ = (Byte *)(p); UInt64 _vvv_ = (v); \
_ppp_[0] = (Byte)(_vvv_ >> 56); \
_ppp_[1] = (Byte)(_vvv_ >> 48); \
_ppp_[2] = (Byte)(_vvv_ >> 40); \
_ppp_[3] = (Byte)(_vvv_ >> 32); \
_ppp_[4] = (Byte)(_vvv_ >> 24); \
_ppp_[5] = (Byte)(_vvv_ >> 16); \
_ppp_[6] = (Byte)(_vvv_ >> 8); \
_ppp_[7] = (Byte)_vvv_; }
#endif
#ifndef GetBe16
#ifdef GetBe16_to32
#define GetBe16(p) ( (UInt16) GetBe16_to32(p))
#else
#define GetBe16(p) ( (UInt16) ( \
((UInt16)((const Byte *)(p))[0] << 8) | \
((const Byte *)(p))[1] ))
#endif
#endif
#if defined(MY_CPU_BE)
@ -564,6 +588,7 @@ problem-4 : performace:
#define SetBe32a(p, v) { *(UInt32 *)(void *)(p) = (v); }
#define SetBe16a(p, v) { *(UInt16 *)(void *)(p) = (v); }
#define GetUi64a(p) GetUi64(p)
#define GetUi32a(p) GetUi32(p)
#define GetUi16a(p) GetUi16(p)
#define SetUi32a(p, v) SetUi32(p, v)
@ -571,6 +596,7 @@ problem-4 : performace:
#elif defined(MY_CPU_LE)
#define GetUi64a(p) (*(const UInt64 *)(const void *)(p))
#define GetUi32a(p) (*(const UInt32 *)(const void *)(p))
#define GetUi16a(p) (*(const UInt16 *)(const void *)(p))
#define SetUi32a(p, v) { *(UInt32 *)(void *)(p) = (v); }
@ -587,6 +613,11 @@ problem-4 : performace:
#endif
#ifndef GetBe16_to32
#define GetBe16_to32(p) GetBe16(p)
#endif
#if defined(MY_CPU_X86_OR_AMD64) \
|| defined(MY_CPU_ARM_OR_ARM64) \
|| defined(MY_CPU_PPC_OR_PPC64)
@ -615,6 +646,7 @@ BoolInt CPU_IsSupported_SSE2(void);
BoolInt CPU_IsSupported_SSSE3(void);
BoolInt CPU_IsSupported_SSE41(void);
BoolInt CPU_IsSupported_SHA(void);
BoolInt CPU_IsSupported_SHA512(void);
BoolInt CPU_IsSupported_PageGB(void);
#elif defined(MY_CPU_ARM_OR_ARM64)
@ -632,6 +664,7 @@ BoolInt CPU_IsSupported_SHA1(void);
BoolInt CPU_IsSupported_SHA2(void);
BoolInt CPU_IsSupported_AES(void);
#endif
BoolInt CPU_IsSupported_SHA512(void);
#endif

View file

@ -1,5 +1,5 @@
/* LzmaEnc.c -- LZMA Encoder
2024-01-24: Igor Pavlov : Public domain */
Igor Pavlov : Public domain */
#include "Precomp.h"
@ -72,11 +72,11 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p)
p->level = level;
if (p->dictSize == 0)
p->dictSize =
( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) :
( level <= 6 ? ((UInt32)1 << (level + 19)) :
( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26)
)));
p->dictSize = (unsigned)level <= 4 ?
(UInt32)1 << (level * 2 + 16) :
(unsigned)level <= sizeof(size_t) / 2 + 4 ?
(UInt32)1 << (level + 20) :
(UInt32)1 << (sizeof(size_t) / 2 + 24);
if (p->dictSize > p->reduceSize)
{
@ -92,8 +92,8 @@ void LzmaEncProps_Normalize(CLzmaEncProps *p)
if (p->lp < 0) p->lp = 0;
if (p->pb < 0) p->pb = 2;
if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
if (p->algo < 0) p->algo = (unsigned)level < 5 ? 0 : 1;
if (p->fb < 0) p->fb = (unsigned)level < 7 ? 32 : 64;
if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
if (p->numHashBytes < 0) p->numHashBytes = (p->btMode ? 4 : 5);
if (p->mc == 0) p->mc = (16 + ((unsigned)p->fb >> 1)) >> (p->btMode ? 0 : 1);

206
C/Md5.c Normal file
View file

@ -0,0 +1,206 @@
/* Md5.c -- MD5 Hash
: Igor Pavlov : Public domain
This code is based on Colin Plumb's public domain md5.c code */
#include "Precomp.h"
#include <string.h>
#include "Md5.h"
#include "RotateDefs.h"
#include "CpuArch.h"
#define MD5_UPDATE_BLOCKS(p) Md5_UpdateBlocks
Z7_NO_INLINE
void Md5_Init(CMd5 *p)
{
p->count = 0;
p->state[0] = 0x67452301;
p->state[1] = 0xefcdab89;
p->state[2] = 0x98badcfe;
p->state[3] = 0x10325476;
}
#if 0 && !defined(MY_CPU_LE_UNALIGN)
// optional optimization for Big-endian processors or processors without unaligned access:
// it is intended to reduce the number of complex LE32 memory reading from 64 to 16.
// But some compilers (sparc, armt) are better without this optimization.
#define Z7_MD5_USE_DATA32_ARRAY
#endif
#define LOAD_DATA(i) GetUi32((const UInt32 *)(const void *)data + (i))
#ifdef Z7_MD5_USE_DATA32_ARRAY
#define D(i) data32[i]
#else
#define D(i) LOAD_DATA(i)
#endif
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
#define R1(i, f, start, step, w, x, y, z, s, k) \
w += D((start + step * (i)) % 16) + k; \
w += f(x, y, z); \
w = rotlFixed(w, s) + x; \
#define R4(i4, f, start, step, s0,s1,s2,s3, k0,k1,k2,k3) \
R1 (i4*4+0, f, start, step, a,b,c,d, s0, k0) \
R1 (i4*4+1, f, start, step, d,a,b,c, s1, k1) \
R1 (i4*4+2, f, start, step, c,d,a,b, s2, k2) \
R1 (i4*4+3, f, start, step, b,c,d,a, s3, k3) \
#define R16(f, start, step, s0,s1,s2,s3, k00,k01,k02,k03, k10,k11,k12,k13, k20,k21,k22,k23, k30,k31,k32,k33) \
R4 (0, f, start, step, s0,s1,s2,s3, k00,k01,k02,k03) \
R4 (1, f, start, step, s0,s1,s2,s3, k10,k11,k12,k13) \
R4 (2, f, start, step, s0,s1,s2,s3, k20,k21,k22,k23) \
R4 (3, f, start, step, s0,s1,s2,s3, k30,k31,k32,k33) \
static
Z7_NO_INLINE
void Z7_FASTCALL Md5_UpdateBlocks(UInt32 state[4], const Byte *data, size_t numBlocks)
{
UInt32 a, b, c, d;
// if (numBlocks == 0) return;
a = state[0];
b = state[1];
c = state[2];
d = state[3];
do
{
#ifdef Z7_MD5_USE_DATA32_ARRAY
UInt32 data32[MD5_NUM_BLOCK_WORDS];
{
#define LOAD_data32_x4(i) { \
data32[i ] = LOAD_DATA(i ); \
data32[i + 1] = LOAD_DATA(i + 1); \
data32[i + 2] = LOAD_DATA(i + 2); \
data32[i + 3] = LOAD_DATA(i + 3); }
#if 1
LOAD_data32_x4 (0 * 4)
LOAD_data32_x4 (1 * 4)
LOAD_data32_x4 (2 * 4)
LOAD_data32_x4 (3 * 4)
#else
unsigned i;
for (i = 0; i < MD5_NUM_BLOCK_WORDS; i += 4)
{
LOAD_data32_x4(i)
}
#endif
}
#endif
R16 (F1, 0, 1, 7,12,17,22, 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821)
R16 (F2, 1, 5, 5, 9,14,20, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a)
R16 (F3, 5, 3, 4,11,16,23, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665)
R16 (F4, 0, 7, 6,10,15,21, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391)
a += state[0];
b += state[1];
c += state[2];
d += state[3];
state[0] = a;
state[1] = b;
state[2] = c;
state[3] = d;
data += MD5_BLOCK_SIZE;
}
while (--numBlocks);
}
#define Md5_UpdateBlock(p) MD5_UPDATE_BLOCKS(p)(p->state, p->buffer, 1)
void Md5_Update(CMd5 *p, const Byte *data, size_t size)
{
if (size == 0)
return;
{
const unsigned pos = (unsigned)p->count & (MD5_BLOCK_SIZE - 1);
const unsigned num = MD5_BLOCK_SIZE - pos;
p->count += size;
if (num > size)
{
memcpy(p->buffer + pos, data, size);
return;
}
if (pos != 0)
{
size -= num;
memcpy(p->buffer + pos, data, num);
data += num;
Md5_UpdateBlock(p);
}
}
{
const size_t numBlocks = size >> 6;
if (numBlocks)
MD5_UPDATE_BLOCKS(p)(p->state, data, numBlocks);
size &= MD5_BLOCK_SIZE - 1;
if (size == 0)
return;
data += (numBlocks << 6);
memcpy(p->buffer, data, size);
}
}
void Md5_Final(CMd5 *p, Byte *digest)
{
unsigned pos = (unsigned)p->count & (MD5_BLOCK_SIZE - 1);
p->buffer[pos++] = 0x80;
if (pos > (MD5_BLOCK_SIZE - 4 * 2))
{
while (pos != MD5_BLOCK_SIZE) { p->buffer[pos++] = 0; }
// memset(&p->buf.buffer[pos], 0, MD5_BLOCK_SIZE - pos);
Md5_UpdateBlock(p);
pos = 0;
}
memset(&p->buffer[pos], 0, (MD5_BLOCK_SIZE - 4 * 2) - pos);
{
const UInt64 numBits = p->count << 3;
#if defined(MY_CPU_LE_UNALIGN)
SetUi64 (p->buffer + MD5_BLOCK_SIZE - 4 * 2, numBits)
#else
SetUi32a(p->buffer + MD5_BLOCK_SIZE - 4 * 2, (UInt32)(numBits))
SetUi32a(p->buffer + MD5_BLOCK_SIZE - 4 * 1, (UInt32)(numBits >> 32))
#endif
}
Md5_UpdateBlock(p);
SetUi32(digest, p->state[0])
SetUi32(digest + 4, p->state[1])
SetUi32(digest + 8, p->state[2])
SetUi32(digest + 12, p->state[3])
Md5_Init(p);
}
#undef R1
#undef R4
#undef R16
#undef D
#undef LOAD_DATA
#undef LOAD_data32_x4
#undef F1
#undef F2
#undef F3
#undef F4

34
C/Md5.h Normal file
View file

@ -0,0 +1,34 @@
/* Md5.h -- MD5 Hash
: Igor Pavlov : Public domain */
#ifndef ZIP7_INC_MD5_H
#define ZIP7_INC_MD5_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#define MD5_NUM_BLOCK_WORDS 16
#define MD5_NUM_DIGEST_WORDS 4
#define MD5_BLOCK_SIZE (MD5_NUM_BLOCK_WORDS * 4)
#define MD5_DIGEST_SIZE (MD5_NUM_DIGEST_WORDS * 4)
typedef struct
{
UInt64 count;
UInt64 _pad_1;
// we want 16-bytes alignment here
UInt32 state[MD5_NUM_DIGEST_WORDS];
UInt64 _pad_2[4];
// we want 64-bytes alignment here
Byte buffer[MD5_BLOCK_SIZE];
} CMd5;
void Md5_Init(CMd5 *p);
void Md5_Update(CMd5 *p, const Byte *data, size_t size);
void Md5_Final(CMd5 *p, Byte *digest);
EXTERN_C_END
#endif

125
C/Sha1.c
View file

@ -1,18 +1,14 @@
/* Sha1.c -- SHA-1 Hash
2024-03-01 : Igor Pavlov : Public domain
: Igor Pavlov : Public domain
This code is based on public domain code of Steve Reid from Wei Dai's Crypto++ library. */
#include "Precomp.h"
#include <string.h>
#include "CpuArch.h"
#include "RotateDefs.h"
#include "Sha1.h"
#if defined(_MSC_VER) && (_MSC_VER < 1900)
// #define USE_MY_MM
#endif
#include "RotateDefs.h"
#include "CpuArch.h"
#ifdef MY_CPU_X86_OR_AMD64
#if defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30800) \
@ -56,7 +52,7 @@ void Z7_FASTCALL Sha1_UpdateBlocks(UInt32 state[5], const Byte *data, size_t num
static SHA1_FUNC_UPDATE_BLOCKS g_SHA1_FUNC_UPDATE_BLOCKS = Sha1_UpdateBlocks;
static SHA1_FUNC_UPDATE_BLOCKS g_SHA1_FUNC_UPDATE_BLOCKS_HW;
#define SHA1_UPDATE_BLOCKS(p) p->func_UpdateBlocks
#define SHA1_UPDATE_BLOCKS(p) p->v.vars.func_UpdateBlocks
#else
#define SHA1_UPDATE_BLOCKS(p) Sha1_UpdateBlocks
#endif
@ -85,7 +81,7 @@ BoolInt Sha1_SetFunction(CSha1 *p, unsigned algo)
return False;
#endif
p->func_UpdateBlocks = func;
p->v.vars.func_UpdateBlocks = func;
return True;
}
@ -225,7 +221,7 @@ BoolInt Sha1_SetFunction(CSha1 *p, unsigned algo)
void Sha1_InitState(CSha1 *p)
{
p->count = 0;
p->v.vars.count = 0;
p->state[0] = 0x67452301;
p->state[1] = 0xEFCDAB89;
p->state[2] = 0x98BADCFE;
@ -235,7 +231,7 @@ void Sha1_InitState(CSha1 *p)
void Sha1_Init(CSha1 *p)
{
p->func_UpdateBlocks =
p->v.vars.func_UpdateBlocks =
#ifdef Z7_COMPILER_SHA1_SUPPORTED
g_SHA1_FUNC_UPDATE_BLOCKS;
#else
@ -250,7 +246,7 @@ void Z7_FASTCALL Sha1_UpdateBlocks(UInt32 state[5], const Byte *data, size_t num
{
UInt32 a, b, c, d, e;
UInt32 W[kNumW];
// if (numBlocks != 0x1264378347) return;
if (numBlocks == 0)
return;
@ -283,7 +279,7 @@ void Z7_FASTCALL Sha1_UpdateBlocks(UInt32 state[5], const Byte *data, size_t num
state[3] = d;
state[4] = e;
data += 64;
data += SHA1_BLOCK_SIZE;
}
while (--numBlocks);
}
@ -295,20 +291,15 @@ void Sha1_Update(CSha1 *p, const Byte *data, size_t size)
{
if (size == 0)
return;
{
unsigned pos = (unsigned)p->count & 0x3F;
unsigned num;
p->count += size;
num = 64 - pos;
const unsigned pos = (unsigned)p->v.vars.count & (SHA1_BLOCK_SIZE - 1);
const unsigned num = SHA1_BLOCK_SIZE - pos;
p->v.vars.count += size;
if (num > size)
{
memcpy(p->buffer + pos, data, size);
return;
}
if (pos != 0)
{
size -= num;
@ -318,9 +309,10 @@ void Sha1_Update(CSha1 *p, const Byte *data, size_t size)
}
}
{
size_t numBlocks = size >> 6;
const size_t numBlocks = size >> 6;
// if (numBlocks)
SHA1_UPDATE_BLOCKS(p)(p->state, data, numBlocks);
size &= 0x3F;
size &= SHA1_BLOCK_SIZE - 1;
if (size == 0)
return;
data += (numBlocks << 6);
@ -331,42 +323,21 @@ void Sha1_Update(CSha1 *p, const Byte *data, size_t size)
void Sha1_Final(CSha1 *p, Byte *digest)
{
unsigned pos = (unsigned)p->count & 0x3F;
unsigned pos = (unsigned)p->v.vars.count & (SHA1_BLOCK_SIZE - 1);
p->buffer[pos++] = 0x80;
if (pos > (64 - 8))
if (pos > (SHA1_BLOCK_SIZE - 4 * 2))
{
while (pos != 64) { p->buffer[pos++] = 0; }
// memset(&p->buf.buffer[pos], 0, 64 - pos);
while (pos != SHA1_BLOCK_SIZE) { p->buffer[pos++] = 0; }
// memset(&p->buf.buffer[pos], 0, SHA1_BLOCK_SIZE - pos);
Sha1_UpdateBlock(p);
pos = 0;
}
/*
if (pos & 3)
memset(&p->buffer[pos], 0, (SHA1_BLOCK_SIZE - 4 * 2) - pos);
{
p->buffer[pos] = 0;
p->buffer[pos + 1] = 0;
p->buffer[pos + 2] = 0;
pos += 3;
pos &= ~3;
const UInt64 numBits = p->v.vars.count << 3;
SetBe32(p->buffer + SHA1_BLOCK_SIZE - 4 * 2, (UInt32)(numBits >> 32))
SetBe32(p->buffer + SHA1_BLOCK_SIZE - 4 * 1, (UInt32)(numBits))
}
{
for (; pos < 64 - 8; pos += 4)
*(UInt32 *)(&p->buffer[pos]) = 0;
}
*/
memset(&p->buffer[pos], 0, (64 - 8) - pos);
{
const UInt64 numBits = (p->count << 3);
SetBe32(p->buffer + 64 - 8, (UInt32)(numBits >> 32))
SetBe32(p->buffer + 64 - 4, (UInt32)(numBits))
}
Sha1_UpdateBlock(p);
SetBe32(digest, p->state[0])
@ -375,16 +346,13 @@ void Sha1_Final(CSha1 *p, Byte *digest)
SetBe32(digest + 12, p->state[3])
SetBe32(digest + 16, p->state[4])
Sha1_InitState(p);
}
void Sha1_PrepareBlock(const CSha1 *p, Byte *block, unsigned size)
{
const UInt64 numBits = (p->count + size) << 3;
const UInt64 numBits = (p->v.vars.count + size) << 3;
SetBe32(&((UInt32 *)(void *)block)[SHA1_NUM_BLOCK_WORDS - 2], (UInt32)(numBits >> 32))
SetBe32(&((UInt32 *)(void *)block)[SHA1_NUM_BLOCK_WORDS - 1], (UInt32)(numBits))
// SetBe32((UInt32 *)(block + size), 0x80000000);
@ -420,57 +388,32 @@ void Sha1_GetBlockDigest(const CSha1 *p, const Byte *data, Byte *destDigest)
void Sha1Prepare(void)
{
#ifdef Z7_COMPILER_SHA1_SUPPORTED
#ifdef Z7_COMPILER_SHA1_SUPPORTED
SHA1_FUNC_UPDATE_BLOCKS f, f_hw;
f = Sha1_UpdateBlocks;
f_hw = NULL;
#ifdef MY_CPU_X86_OR_AMD64
#ifndef USE_MY_MM
#ifdef MY_CPU_X86_OR_AMD64
if (CPU_IsSupported_SHA()
&& CPU_IsSupported_SSSE3()
// && CPU_IsSupported_SSE41()
)
#endif
#else
#else
if (CPU_IsSupported_SHA1())
#endif
#endif
{
// printf("\n========== HW SHA1 ======== \n");
#if 0 && defined(MY_CPU_ARM_OR_ARM64) && defined(_MSC_VER)
#if 1 && defined(MY_CPU_ARM_OR_ARM64) && defined(Z7_MSC_VER_ORIGINAL) && (_MSC_FULL_VER < 192930037)
/* there was bug in MSVC compiler for ARM64 -O2 before version VS2019 16.10 (19.29.30037).
It generated incorrect SHA-1 code.
21.03 : we test sha1-hardware code at runtime initialization */
#pragma message("== SHA1 code: MSC compiler : failure-check code was inserted")
UInt32 state[5] = { 0, 1, 2, 3, 4 } ;
Byte data[64];
unsigned i;
for (i = 0; i < sizeof(data); i += 2)
{
data[i ] = (Byte)(i);
data[i + 1] = (Byte)(i + 1);
}
Sha1_UpdateBlocks_HW(state, data, sizeof(data) / 64);
if ( state[0] != 0x9acd7297
|| state[1] != 0x4624d898
|| state[2] != 0x0bf079f0
|| state[3] != 0x031e61b3
|| state[4] != 0x8323fe20)
{
// printf("\n========== SHA-1 hardware version failure ======== \n");
}
else
#endif
It generated incorrect SHA-1 code. */
#pragma message("== SHA1 code can work incorrectly with this compiler")
#error Stop_Compiling_MSC_Compiler_BUG_SHA1
#endif
{
f = f_hw = Sha1_UpdateBlocks_HW;
}
}
g_SHA1_FUNC_UPDATE_BLOCKS = f;
g_SHA1_FUNC_UPDATE_BLOCKS_HW = f_hw;
#endif
#endif
}
#undef kNumW

View file

@ -1,5 +1,5 @@
/* Sha1.h -- SHA-1 Hash
2023-04-02 : Igor Pavlov : Public domain */
: Igor Pavlov : Public domain */
#ifndef ZIP7_INC_SHA1_H
#define ZIP7_INC_SHA1_H
@ -14,6 +14,9 @@ EXTERN_C_BEGIN
#define SHA1_BLOCK_SIZE (SHA1_NUM_BLOCK_WORDS * 4)
#define SHA1_DIGEST_SIZE (SHA1_NUM_DIGEST_WORDS * 4)
typedef void (Z7_FASTCALL *SHA1_FUNC_UPDATE_BLOCKS)(UInt32 state[5], const Byte *data, size_t numBlocks);
/*
@ -32,9 +35,16 @@ typedef void (Z7_FASTCALL *SHA1_FUNC_UPDATE_BLOCKS)(UInt32 state[5], const Byte
typedef struct
{
SHA1_FUNC_UPDATE_BLOCKS func_UpdateBlocks;
UInt64 count;
UInt64 _pad_2[2];
union
{
struct
{
SHA1_FUNC_UPDATE_BLOCKS func_UpdateBlocks;
UInt64 count;
} vars;
UInt64 _pad_64bit[4];
void *_pad_align_ptr[2];
} v;
UInt32 state[SHA1_NUM_DIGEST_WORDS];
UInt32 _pad_3[3];
Byte buffer[SHA1_BLOCK_SIZE];

View file

@ -1,18 +1,11 @@
/* Sha1Opt.c -- SHA-1 optimized code for SHA-1 hardware instructions
2024-03-01 : Igor Pavlov : Public domain */
: Igor Pavlov : Public domain */
#include "Precomp.h"
#include "Compiler.h"
#include "CpuArch.h"
#if defined(_MSC_VER)
#if (_MSC_VER < 1900) && (_MSC_VER >= 1200)
// #define USE_MY_MM
#endif
#endif
// #define Z7_USE_HW_SHA_STUB // for debug
#ifdef MY_CPU_X86_OR_AMD64
#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) // fix that check
#define USE_HW_SHA
@ -20,19 +13,14 @@
|| defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 50100) \
|| defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900)
#define USE_HW_SHA
#if !defined(_INTEL_COMPILER)
#if !defined(__INTEL_COMPILER)
// icc defines __GNUC__, but icc doesn't support __attribute__(__target__)
#if !defined(__SHA__) || !defined(__SSSE3__)
#define ATTRIB_SHA __attribute__((__target__("sha,ssse3")))
#endif
#endif
#elif defined(_MSC_VER)
#ifdef USE_MY_MM
#define USE_VER_MIN 1300
#else
#define USE_VER_MIN 1900
#endif
#if (_MSC_VER >= USE_VER_MIN)
#if (_MSC_VER >= 1900)
#define USE_HW_SHA
#else
#define Z7_USE_HW_SHA_STUB
@ -47,23 +35,20 @@
// #pragma message("Sha1 HW")
// sse/sse2/ssse3:
#include <tmmintrin.h>
// sha*:
#include <immintrin.h>
#if defined (__clang__) && defined(_MSC_VER)
// #if !defined(__SSSE3__)
// #endif
#if !defined(__SHA__)
#include <shaintrin.h>
#endif
#else
#ifdef USE_MY_MM
#include "My_mm.h"
#endif
#endif
/*
@ -84,7 +69,6 @@ SHA:
_mm_sha1*
*/
#define XOR_SI128(dest, src) dest = _mm_xor_si128(dest, src);
#define SHUFFLE_EPI8(dest, mask) dest = _mm_shuffle_epi8(dest, mask);
#define SHUFFLE_EPI32(dest, mask) dest = _mm_shuffle_epi32(dest, mask);
@ -99,11 +83,12 @@ SHA:
#define SHA1_MSG1(dest, src) dest = _mm_sha1msg1_epu32(dest, src);
#define SHA1_MSG2(dest, src) dest = _mm_sha1msg2_epu32(dest, src);
#define LOAD_SHUFFLE(m, k) \
m = _mm_loadu_si128((const __m128i *)(const void *)(data + (k) * 16)); \
SHUFFLE_EPI8(m, mask) \
#define NNN(m0, m1, m2, m3)
#define SM1(m0, m1, m2, m3) \
SHA1_MSG1(m0, m1) \
@ -116,35 +101,19 @@ SHA:
SM1(m0, m1, m2, m3) \
SHA1_MSG2(m3, m2) \
#define NNN(m0, m1, m2, m3)
#define R4(k, e0, e1, m0, m1, m2, m3, OP) \
#define R4(k, m0, m1, m2, m3, e0, e1, OP) \
e1 = abcd; \
SHA1_RND4(abcd, e0, (k) / 5) \
SHA1_NEXTE(e1, m1) \
OP(m0, m1, m2, m3) \
#define R16(k, mx, OP0, OP1, OP2, OP3) \
R4 ( (k)*4+0, e0,e1, m0,m1,m2,m3, OP0 ) \
R4 ( (k)*4+1, e1,e0, m1,m2,m3,m0, OP1 ) \
R4 ( (k)*4+2, e0,e1, m2,m3,m0,m1, OP2 ) \
R4 ( (k)*4+3, e1,e0, m3,mx,m1,m2, OP3 ) \
R4 ( (k)*4+0, m0,m1,m2,m3, e0,e1, OP0 ) \
R4 ( (k)*4+1, m1,m2,m3,m0, e1,e0, OP1 ) \
R4 ( (k)*4+2, m2,m3,m0,m1, e0,e1, OP2 ) \
R4 ( (k)*4+3, m3,mx,m1,m2, e1,e0, OP3 ) \
#define PREPARE_STATE \
SHUFFLE_EPI32 (abcd, 0x1B) \
@ -162,8 +131,9 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t
{
const __m128i mask = _mm_set_epi32(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f);
__m128i abcd, e0;
__m128i abcd, e0;
if (numBlocks == 0)
return;
@ -204,7 +174,7 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t
PREPARE_STATE
_mm_storeu_si128((__m128i *) (void *) state, abcd);
*(state+4) = (UInt32)_mm_cvtsi128_si32(e0);
*(state + 4) = (UInt32)_mm_cvtsi128_si32(e0);
}
#endif // USE_HW_SHA
@ -262,22 +232,10 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t
#define _ARM_USE_NEW_NEON_INTRINSICS
#endif
#if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64)
#include <arm64_neon.h>
#else
#if defined(__clang__) && __clang_major__ < 16
#if !defined(__ARM_FEATURE_SHA2) && \
!defined(__ARM_FEATURE_CRYPTO)
@ -329,26 +287,37 @@ typedef uint32x4_t v128;
#endif
#ifdef MY_CPU_BE
#define MY_rev32_for_LE(x)
#define MY_rev32_for_LE(x) x
#else
#define MY_rev32_for_LE(x) x = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(x)))
#define MY_rev32_for_LE(x) vrev32q_u8(x)
#endif
#define LOAD_128(_p) (*(const v128 *)(const void *)(_p))
#define STORE_128(_p, _v) *(v128 *)(void *)(_p) = (_v)
#define LOAD_128_32(_p) vld1q_u32(_p)
#define LOAD_128_8(_p) vld1q_u8 (_p)
#define STORE_128_32(_p, _v) vst1q_u32(_p, _v)
#define LOAD_SHUFFLE(m, k) \
m = LOAD_128((data + (k) * 16)); \
MY_rev32_for_LE(m); \
m = vreinterpretq_u32_u8( \
MY_rev32_for_LE( \
LOAD_128_8(data + (k) * 16))); \
#define SU0(dest, src2, src3) dest = vsha1su0q_u32(dest, src2, src3)
#define SU1(dest, src) dest = vsha1su1q_u32(dest, src)
#define N0(dest, src2, src3)
#define N1(dest, src)
#define U0(dest, src2, src3) dest = vsha1su0q_u32(dest, src2, src3);
#define U1(dest, src) dest = vsha1su1q_u32(dest, src);
#define C(e) abcd = vsha1cq_u32(abcd, e, t)
#define P(e) abcd = vsha1pq_u32(abcd, e, t)
#define M(e) abcd = vsha1mq_u32(abcd, e, t)
#define H(e) e = vsha1h_u32(vgetq_lane_u32(abcd, 0))
#define T(m, c) t = vaddq_u32(m, c)
#define R16(d0,d1,d2,d3, f0,z0, f1,z1, f2,z2, f3,z3, w0,w1,w2,w3) \
T(m0, d0); f0(m3, m0, m1) z0(m2, m1) H(e1); w0(e0); \
T(m1, d1); f1(m0, m1, m2) z1(m3, m2) H(e0); w1(e1); \
T(m2, d2); f2(m1, m2, m3) z2(m0, m3) H(e1); w2(e0); \
T(m3, d3); f3(m2, m3, m0) z3(m1, m0) H(e0); w3(e1); \
void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks);
#ifdef ATTRIB_SHA
ATTRIB_SHA
@ -367,7 +336,7 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t
c2 = vdupq_n_u32(0x8f1bbcdc);
c3 = vdupq_n_u32(0xca62c1d6);
abcd = LOAD_128(&state[0]);
abcd = LOAD_128_32(&state[0]);
e0 = state[4];
do
@ -385,26 +354,11 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t
LOAD_SHUFFLE (m2, 2)
LOAD_SHUFFLE (m3, 3)
T(m0, c0); H(e1); C(e0);
T(m1, c0); SU0(m0, m1, m2); H(e0); C(e1);
T(m2, c0); SU0(m1, m2, m3); SU1(m0, m3); H(e1); C(e0);
T(m3, c0); SU0(m2, m3, m0); SU1(m1, m0); H(e0); C(e1);
T(m0, c0); SU0(m3, m0, m1); SU1(m2, m1); H(e1); C(e0);
T(m1, c1); SU0(m0, m1, m2); SU1(m3, m2); H(e0); P(e1);
T(m2, c1); SU0(m1, m2, m3); SU1(m0, m3); H(e1); P(e0);
T(m3, c1); SU0(m2, m3, m0); SU1(m1, m0); H(e0); P(e1);
T(m0, c1); SU0(m3, m0, m1); SU1(m2, m1); H(e1); P(e0);
T(m1, c1); SU0(m0, m1, m2); SU1(m3, m2); H(e0); P(e1);
T(m2, c2); SU0(m1, m2, m3); SU1(m0, m3); H(e1); M(e0);
T(m3, c2); SU0(m2, m3, m0); SU1(m1, m0); H(e0); M(e1);
T(m0, c2); SU0(m3, m0, m1); SU1(m2, m1); H(e1); M(e0);
T(m1, c2); SU0(m0, m1, m2); SU1(m3, m2); H(e0); M(e1);
T(m2, c2); SU0(m1, m2, m3); SU1(m0, m3); H(e1); M(e0);
T(m3, c3); SU0(m2, m3, m0); SU1(m1, m0); H(e0); P(e1);
T(m0, c3); SU0(m3, m0, m1); SU1(m2, m1); H(e1); P(e0);
T(m1, c3); SU1(m3, m2); H(e0); P(e1);
T(m2, c3); H(e1); P(e0);
T(m3, c3); H(e0); P(e1);
R16 ( c0,c0,c0,c0, N0,N1, U0,N1, U0,U1, U0,U1, C,C,C,C )
R16 ( c0,c1,c1,c1, U0,U1, U0,U1, U0,U1, U0,U1, C,P,P,P )
R16 ( c1,c1,c2,c2, U0,U1, U0,U1, U0,U1, U0,U1, P,P,M,M )
R16 ( c2,c2,c2,c3, U0,U1, U0,U1, U0,U1, U0,U1, M,M,M,P )
R16 ( c3,c3,c3,c3, U0,U1, N0,U1, N0,N1, N0,N1, P,P,P,P )
abcd = vaddq_u32(abcd, abcd_save);
e0 += e0_save;
@ -413,7 +367,7 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t
}
while (--numBlocks);
STORE_128(&state[0], abcd);
STORE_128_32(&state[0], abcd);
state[4] = e0;
}
@ -421,13 +375,9 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t
#endif // MY_CPU_ARM_OR_ARM64
#if !defined(USE_HW_SHA) && defined(Z7_USE_HW_SHA_STUB)
// #error Stop_Compiling_UNSUPPORTED_SHA
// #include <stdlib.h>
// #include "Sha1.h"
// #if defined(_MSC_VER)
#pragma message("Sha1 HW-SW stub was used")
@ -447,8 +397,10 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t
}
#endif
#undef SU0
#undef SU1
#undef U0
#undef U1
#undef N0
#undef N1
#undef C
#undef P
#undef M

View file

@ -1,18 +1,14 @@
/* Sha256.c -- SHA-256 Hash
2024-03-01 : Igor Pavlov : Public domain
: Igor Pavlov : Public domain
This code is based on public domain code from Wei Dai's Crypto++ library. */
#include "Precomp.h"
#include <string.h>
#include "CpuArch.h"
#include "RotateDefs.h"
#include "Sha256.h"
#if defined(_MSC_VER) && (_MSC_VER < 1900)
// #define USE_MY_MM
#endif
#include "RotateDefs.h"
#include "CpuArch.h"
#ifdef MY_CPU_X86_OR_AMD64
#if defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30800) \
@ -56,7 +52,7 @@ void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t n
static SHA256_FUNC_UPDATE_BLOCKS g_SHA256_FUNC_UPDATE_BLOCKS = Sha256_UpdateBlocks;
static SHA256_FUNC_UPDATE_BLOCKS g_SHA256_FUNC_UPDATE_BLOCKS_HW;
#define SHA256_UPDATE_BLOCKS(p) p->func_UpdateBlocks
#define SHA256_UPDATE_BLOCKS(p) p->v.vars.func_UpdateBlocks
#else
#define SHA256_UPDATE_BLOCKS(p) Sha256_UpdateBlocks
#endif
@ -85,7 +81,7 @@ BoolInt Sha256_SetFunction(CSha256 *p, unsigned algo)
return False;
#endif
p->func_UpdateBlocks = func;
p->v.vars.func_UpdateBlocks = func;
return True;
}
@ -111,7 +107,7 @@ BoolInt Sha256_SetFunction(CSha256 *p, unsigned algo)
void Sha256_InitState(CSha256 *p)
{
p->count = 0;
p->v.vars.count = 0;
p->state[0] = 0x6a09e667;
p->state[1] = 0xbb67ae85;
p->state[2] = 0x3c6ef372;
@ -122,9 +118,16 @@ void Sha256_InitState(CSha256 *p)
p->state[7] = 0x5be0cd19;
}
void Sha256_Init(CSha256 *p)
{
p->func_UpdateBlocks =
p->v.vars.func_UpdateBlocks =
#ifdef Z7_COMPILER_SHA256_SUPPORTED
g_SHA256_FUNC_UPDATE_BLOCKS;
#else
@ -133,10 +136,10 @@ void Sha256_Init(CSha256 *p)
Sha256_InitState(p);
}
#define S0(x) (rotrFixed(x, 2) ^ rotrFixed(x,13) ^ rotrFixed(x, 22))
#define S1(x) (rotrFixed(x, 6) ^ rotrFixed(x,11) ^ rotrFixed(x, 25))
#define S0(x) (rotrFixed(x, 2) ^ rotrFixed(x,13) ^ rotrFixed(x,22))
#define S1(x) (rotrFixed(x, 6) ^ rotrFixed(x,11) ^ rotrFixed(x,25))
#define s0(x) (rotrFixed(x, 7) ^ rotrFixed(x,18) ^ (x >> 3))
#define s1(x) (rotrFixed(x,17) ^ rotrFixed(x,19) ^ (x >> 10))
#define s1(x) (rotrFixed(x,17) ^ rotrFixed(x,19) ^ (x >>10))
#define Ch(x,y,z) (z^(x&(y^z)))
#define Maj(x,y,z) ((x&y)|(z&(x|y)))
@ -224,12 +227,10 @@ void Sha256_Init(CSha256 *p)
#endif
// static
extern MY_ALIGN(64)
const UInt32 SHA256_K_ARRAY[64];
MY_ALIGN(64)
const UInt32 SHA256_K_ARRAY[64] = {
extern
MY_ALIGN(64) const UInt32 SHA256_K_ARRAY[64];
MY_ALIGN(64) const UInt32 SHA256_K_ARRAY[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
@ -248,27 +249,29 @@ const UInt32 SHA256_K_ARRAY[64] = {
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
#define K SHA256_K_ARRAY
#define K SHA256_K_ARRAY
Z7_NO_INLINE
void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t numBlocks)
{
UInt32 W
#ifdef Z7_SHA256_BIG_W
#ifdef Z7_SHA256_BIG_W
[64];
#else
#else
[16];
#endif
#endif
unsigned j;
UInt32 a,b,c,d,e,f,g,h;
#if !defined(Z7_SHA256_UNROLL) || (STEP_MAIN <= 4) || (STEP_PRE <= 4)
#if !defined(Z7_SHA256_UNROLL) || (STEP_MAIN <= 4) || (STEP_PRE <= 4)
UInt32 tmp;
#endif
#endif
if (numBlocks == 0) return;
a = state[0];
b = state[1];
c = state[2];
@ -278,7 +281,7 @@ void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t n
g = state[6];
h = state[7];
while (numBlocks)
do
{
for (j = 0; j < 16; j += STEP_PRE)
@ -352,19 +355,11 @@ void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t n
g += state[6]; state[6] = g;
h += state[7]; state[7] = h;
data += 64;
numBlocks--;
data += SHA256_BLOCK_SIZE;
}
/* Wipe variables */
/* memset(W, 0, sizeof(W)); */
while (--numBlocks);
}
#undef S0
#undef S1
#undef s0
#undef s1
#undef K
#define Sha256_UpdateBlock(p) SHA256_UPDATE_BLOCKS(p)(p->state, p->buffer, 1)
@ -372,20 +367,15 @@ void Sha256_Update(CSha256 *p, const Byte *data, size_t size)
{
if (size == 0)
return;
{
unsigned pos = (unsigned)p->count & 0x3F;
unsigned num;
p->count += size;
num = 64 - pos;
const unsigned pos = (unsigned)p->v.vars.count & (SHA256_BLOCK_SIZE - 1);
const unsigned num = SHA256_BLOCK_SIZE - pos;
p->v.vars.count += size;
if (num > size)
{
memcpy(p->buffer + pos, data, size);
return;
}
if (pos != 0)
{
size -= num;
@ -395,9 +385,10 @@ void Sha256_Update(CSha256 *p, const Byte *data, size_t size)
}
}
{
size_t numBlocks = size >> 6;
const size_t numBlocks = size >> 6;
// if (numBlocks)
SHA256_UPDATE_BLOCKS(p)(p->state, data, numBlocks);
size &= 0x3F;
size &= SHA256_BLOCK_SIZE - 1;
if (size == 0)
return;
data += (numBlocks << 6);
@ -408,82 +399,69 @@ void Sha256_Update(CSha256 *p, const Byte *data, size_t size)
void Sha256_Final(CSha256 *p, Byte *digest)
{
unsigned pos = (unsigned)p->count & 0x3F;
unsigned i;
unsigned pos = (unsigned)p->v.vars.count & (SHA256_BLOCK_SIZE - 1);
p->buffer[pos++] = 0x80;
if (pos > (64 - 8))
if (pos > (SHA256_BLOCK_SIZE - 4 * 2))
{
while (pos != 64) { p->buffer[pos++] = 0; }
// memset(&p->buf.buffer[pos], 0, 64 - pos);
while (pos != SHA256_BLOCK_SIZE) { p->buffer[pos++] = 0; }
// memset(&p->buf.buffer[pos], 0, SHA256_BLOCK_SIZE - pos);
Sha256_UpdateBlock(p);
pos = 0;
}
/*
if (pos & 3)
memset(&p->buffer[pos], 0, (SHA256_BLOCK_SIZE - 4 * 2) - pos);
{
p->buffer[pos] = 0;
p->buffer[pos + 1] = 0;
p->buffer[pos + 2] = 0;
pos += 3;
pos &= ~3;
const UInt64 numBits = p->v.vars.count << 3;
SetBe32(p->buffer + SHA256_BLOCK_SIZE - 4 * 2, (UInt32)(numBits >> 32))
SetBe32(p->buffer + SHA256_BLOCK_SIZE - 4 * 1, (UInt32)(numBits))
}
{
for (; pos < 64 - 8; pos += 4)
*(UInt32 *)(&p->buffer[pos]) = 0;
}
*/
memset(&p->buffer[pos], 0, (64 - 8) - pos);
{
UInt64 numBits = (p->count << 3);
SetBe32(p->buffer + 64 - 8, (UInt32)(numBits >> 32))
SetBe32(p->buffer + 64 - 4, (UInt32)(numBits))
}
Sha256_UpdateBlock(p);
for (i = 0; i < 8; i += 2)
#if 1 && defined(MY_CPU_BE)
memcpy(digest, p->state, SHA256_DIGEST_SIZE);
#else
{
UInt32 v0 = p->state[i];
UInt32 v1 = p->state[(size_t)i + 1];
SetBe32(digest , v0)
SetBe32(digest + 4, v1)
digest += 8;
unsigned i;
for (i = 0; i < 8; i += 2)
{
const UInt32 v0 = p->state[i];
const UInt32 v1 = p->state[(size_t)i + 1];
SetBe32(digest , v0)
SetBe32(digest + 4, v1)
digest += 4 * 2;
}
}
#endif
Sha256_InitState(p);
}
void Sha256Prepare(void)
{
#ifdef Z7_COMPILER_SHA256_SUPPORTED
#ifdef Z7_COMPILER_SHA256_SUPPORTED
SHA256_FUNC_UPDATE_BLOCKS f, f_hw;
f = Sha256_UpdateBlocks;
f_hw = NULL;
#ifdef MY_CPU_X86_OR_AMD64
#ifndef USE_MY_MM
#ifdef MY_CPU_X86_OR_AMD64
if (CPU_IsSupported_SHA()
&& CPU_IsSupported_SSSE3()
// && CPU_IsSupported_SSE41()
)
#endif
#else
#else
if (CPU_IsSupported_SHA2())
#endif
#endif
{
// printf("\n========== HW SHA256 ======== \n");
f = f_hw = Sha256_UpdateBlocks_HW;
}
g_SHA256_FUNC_UPDATE_BLOCKS = f;
g_SHA256_FUNC_UPDATE_BLOCKS_HW = f_hw;
#endif
#endif
}
#undef U64C
#undef K
#undef S0
#undef S1
#undef s0

View file

@ -1,5 +1,5 @@
/* Sha256.h -- SHA-256 Hash
2023-04-02 : Igor Pavlov : Public domain */
: Igor Pavlov : Public domain */
#ifndef ZIP7_INC_SHA256_H
#define ZIP7_INC_SHA256_H
@ -14,6 +14,9 @@ EXTERN_C_BEGIN
#define SHA256_BLOCK_SIZE (SHA256_NUM_BLOCK_WORDS * 4)
#define SHA256_DIGEST_SIZE (SHA256_NUM_DIGEST_WORDS * 4)
typedef void (Z7_FASTCALL *SHA256_FUNC_UPDATE_BLOCKS)(UInt32 state[8], const Byte *data, size_t numBlocks);
/*
@ -32,9 +35,16 @@ typedef void (Z7_FASTCALL *SHA256_FUNC_UPDATE_BLOCKS)(UInt32 state[8], const Byt
typedef struct
{
SHA256_FUNC_UPDATE_BLOCKS func_UpdateBlocks;
UInt64 count;
UInt64 _pad_2[2];
union
{
struct
{
SHA256_FUNC_UPDATE_BLOCKS func_UpdateBlocks;
UInt64 count;
} vars;
UInt64 _pad_64bit[4];
void *_pad_align_ptr[2];
} v;
UInt32 state[SHA256_NUM_DIGEST_WORDS];
Byte buffer[SHA256_BLOCK_SIZE];

View file

@ -1,18 +1,11 @@
/* Sha256Opt.c -- SHA-256 optimized code for SHA-256 hardware instructions
2024-03-01 : Igor Pavlov : Public domain */
: Igor Pavlov : Public domain */
#include "Precomp.h"
#include "Compiler.h"
#include "CpuArch.h"
#if defined(_MSC_VER)
#if (_MSC_VER < 1900) && (_MSC_VER >= 1200)
// #define USE_MY_MM
#endif
#endif
// #define Z7_USE_HW_SHA_STUB // for debug
#ifdef MY_CPU_X86_OR_AMD64
#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) // fix that check
#define USE_HW_SHA
@ -20,19 +13,14 @@
|| defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 50100) \
|| defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900)
#define USE_HW_SHA
#if !defined(_INTEL_COMPILER)
#if !defined(__INTEL_COMPILER)
// icc defines __GNUC__, but icc doesn't support __attribute__(__target__)
#if !defined(__SHA__) || !defined(__SSSE3__)
#define ATTRIB_SHA __attribute__((__target__("sha,ssse3")))
#endif
#endif
#elif defined(_MSC_VER)
#ifdef USE_MY_MM
#define USE_VER_MIN 1300
#else
#define USE_VER_MIN 1900
#endif
#if (_MSC_VER >= USE_VER_MIN)
#if (_MSC_VER >= 1900)
#define USE_HW_SHA
#else
#define Z7_USE_HW_SHA_STUB
@ -47,23 +35,20 @@
// #pragma message("Sha256 HW")
// sse/sse2/ssse3:
#include <tmmintrin.h>
// sha*:
#include <immintrin.h>
#if defined (__clang__) && defined(_MSC_VER)
// #if !defined(__SSSE3__)
// #endif
#if !defined(__SHA__)
#include <shaintrin.h>
#endif
#else
#ifdef USE_MY_MM
#include "My_mm.h"
#endif
#endif
/*
@ -91,60 +76,44 @@ SHA:
extern
MY_ALIGN(64)
const UInt32 SHA256_K_ARRAY[64];
#define K SHA256_K_ARRAY
#define ADD_EPI32(dest, src) dest = _mm_add_epi32(dest, src);
#define SHA256_MSG1(dest, src) dest = _mm_sha256msg1_epu32(dest, src);
#define SHA25G_MSG2(dest, src) dest = _mm_sha256msg2_epu32(dest, src);
#define SHA256_MSG2(dest, src) dest = _mm_sha256msg2_epu32(dest, src);
#define LOAD_SHUFFLE(m, k) \
m = _mm_loadu_si128((const __m128i *)(const void *)(data + (k) * 16)); \
m = _mm_shuffle_epi8(m, mask); \
#define SM1(g0, g1, g2, g3) \
SHA256_MSG1(g3, g0); \
#define NNN(m0, m1, m2, m3)
#define SM2(g0, g1, g2, g3) \
tmp = _mm_alignr_epi8(g1, g0, 4); \
ADD_EPI32(g2, tmp) \
SHA25G_MSG2(g2, g1); \
// #define LS0(k, g0, g1, g2, g3) LOAD_SHUFFLE(g0, k)
// #define LS1(k, g0, g1, g2, g3) LOAD_SHUFFLE(g1, k+1)
#define NNN(g0, g1, g2, g3)
#define SM1(m1, m2, m3, m0) \
SHA256_MSG1(m0, m1); \
#define SM2(m2, m3, m0, m1) \
ADD_EPI32(m0, _mm_alignr_epi8(m3, m2, 4)) \
SHA256_MSG2(m0, m3); \
#define RND2(t0, t1) \
t0 = _mm_sha256rnds2_epu32(t0, t1, msg);
#define RND2_0(m, k) \
msg = _mm_add_epi32(m, *(const __m128i *) (const void *) &K[(k) * 4]); \
#define R4(k, m0, m1, m2, m3, OP0, OP1) \
msg = _mm_add_epi32(m0, *(const __m128i *) (const void *) &K[(k) * 4]); \
RND2(state0, state1); \
msg = _mm_shuffle_epi32(msg, 0x0E); \
#define RND2_1 \
OP0(m0, m1, m2, m3) \
RND2(state1, state0); \
// We use scheme with 3 rounds ahead for SHA256_MSG1 / 2 rounds ahead for SHA256_MSG2
#define R4(k, g0, g1, g2, g3, OP0, OP1) \
RND2_0(g0, k) \
OP0(g0, g1, g2, g3) \
RND2_1 \
OP1(g0, g1, g2, g3) \
OP1(m0, m1, m2, m3) \
#define R16(k, OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7) \
R4 ( (k)*4+0, m0,m1,m2,m3, OP0, OP1 ) \
R4 ( (k)*4+1, m1,m2,m3,m0, OP2, OP3 ) \
R4 ( (k)*4+2, m2,m3,m0,m1, OP4, OP5 ) \
R4 ( (k)*4+3, m3,m0,m1,m2, OP6, OP7 ) \
R4 ( (k)*4+0, m0,m1,m2,m3, OP0, OP1 ) \
R4 ( (k)*4+1, m1,m2,m3,m0, OP2, OP3 ) \
R4 ( (k)*4+2, m2,m3,m0,m1, OP4, OP5 ) \
R4 ( (k)*4+3, m3,m0,m1,m2, OP6, OP7 ) \
#define PREPARE_STATE \
tmp = _mm_shuffle_epi32(state0, 0x1B); /* abcd */ \
@ -161,8 +130,9 @@ ATTRIB_SHA
void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks)
{
const __m128i mask = _mm_set_epi32(0x0c0d0e0f, 0x08090a0b, 0x04050607, 0x00010203);
__m128i tmp;
__m128i state0, state1;
__m128i tmp, state0, state1;
if (numBlocks == 0)
return;
@ -262,22 +232,10 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
#define _ARM_USE_NEW_NEON_INTRINSICS
#endif
#if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64)
#include <arm64_neon.h>
#else
#if defined(__clang__) && __clang_major__ < 16
#if !defined(__ARM_FEATURE_SHA2) && \
!defined(__ARM_FEATURE_CRYPTO)
@ -324,41 +282,70 @@ typedef uint32x4_t v128;
// typedef __n128 v128; // MSVC
#ifdef MY_CPU_BE
#define MY_rev32_for_LE(x)
#define MY_rev32_for_LE(x) x
#else
#define MY_rev32_for_LE(x) x = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(x)))
#define MY_rev32_for_LE(x) vrev32q_u8(x)
#endif
#define LOAD_128(_p) (*(const v128 *)(const void *)(_p))
#define STORE_128(_p, _v) *(v128 *)(void *)(_p) = (_v)
#if 1 // 0 for debug
// for arm32: it works slower by some reason than direct code
/*
for arm32 it generates:
MSVC-2022, GCC-9:
vld1.32 {d18,d19}, [r10]
vst1.32 {d4,d5}, [r3]
vld1.8 {d20-d21}, [r4]
there is no align hint (like [r10:128]). So instruction allows unaligned access
*/
#define LOAD_128_32(_p) vld1q_u32(_p)
#define LOAD_128_8(_p) vld1q_u8 (_p)
#define STORE_128_32(_p, _v) vst1q_u32(_p, _v)
#else
/*
for arm32:
MSVC-2022:
vldm r10,{d18,d19}
vstm r3,{d4,d5}
does it require strict alignment?
GCC-9:
vld1.64 {d30-d31}, [r0:64]
vldr d28, [r0, #16]
vldr d29, [r0, #24]
vst1.64 {d30-d31}, [r0:64]
vstr d28, [r0, #16]
vstr d29, [r0, #24]
there is hint [r0:64], so does it requires 64-bit alignment.
*/
#define LOAD_128_32(_p) (*(const v128 *)(const void *)(_p))
#define LOAD_128_8(_p) vreinterpretq_u8_u32(*(const v128 *)(const void *)(_p))
#define STORE_128_32(_p, _v) *(v128 *)(void *)(_p) = (_v)
#endif
#define LOAD_SHUFFLE(m, k) \
m = LOAD_128((data + (k) * 16)); \
MY_rev32_for_LE(m); \
m = vreinterpretq_u32_u8( \
MY_rev32_for_LE( \
LOAD_128_8(data + (k) * 16))); \
// K array must be aligned for 16-bytes at least.
extern
MY_ALIGN(64)
const UInt32 SHA256_K_ARRAY[64];
#define K SHA256_K_ARRAY
#define SHA256_SU0(dest, src) dest = vsha256su0q_u32(dest, src);
#define SHA25G_SU1(dest, src2, src3) dest = vsha256su1q_u32(dest, src2, src3);
#define SHA256_SU1(dest, src2, src3) dest = vsha256su1q_u32(dest, src2, src3);
#define SM1(g0, g1, g2, g3) SHA256_SU0(g3, g0)
#define SM2(g0, g1, g2, g3) SHA25G_SU1(g2, g0, g1)
#define NNN(g0, g1, g2, g3)
#define SM1(m0, m1, m2, m3) SHA256_SU0(m3, m0)
#define SM2(m0, m1, m2, m3) SHA256_SU1(m2, m0, m1)
#define NNN(m0, m1, m2, m3)
#define R4(k, g0, g1, g2, g3, OP0, OP1) \
msg = vaddq_u32(g0, *(const v128 *) (const void *) &K[(k) * 4]); \
#define R4(k, m0, m1, m2, m3, OP0, OP1) \
msg = vaddq_u32(m0, *(const v128 *) (const void *) &K[(k) * 4]); \
tmp = state0; \
state0 = vsha256hq_u32( state0, state1, msg ); \
state1 = vsha256h2q_u32( state1, tmp, msg ); \
OP0(g0, g1, g2, g3); \
OP1(g0, g1, g2, g3); \
OP0(m0, m1, m2, m3); \
OP1(m0, m1, m2, m3); \
#define R16(k, OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7) \
@ -379,8 +366,8 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
if (numBlocks == 0)
return;
state0 = LOAD_128(&state[0]);
state1 = LOAD_128(&state[4]);
state0 = LOAD_128_32(&state[0]);
state1 = LOAD_128_32(&state[4]);
do
{
@ -408,8 +395,8 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
}
while (--numBlocks);
STORE_128(&state[0], state0);
STORE_128(&state[4], state1);
STORE_128_32(&state[0], state0);
STORE_128_32(&state[4], state1);
}
#endif // USE_HW_SHA
@ -443,13 +430,10 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
#endif
#undef K
#undef RND2
#undef RND2_0
#undef RND2_1
#undef MY_rev32_for_LE
#undef NNN
#undef LOAD_128
#undef STORE_128
@ -457,7 +441,7 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
#undef SM1
#undef SM2
#undef NNN
#undef R4
#undef R16
#undef PREPARE_STATE

359
C/Sha3.c Normal file
View file

@ -0,0 +1,359 @@
/* Sha3.c -- SHA-3 Hash
: Igor Pavlov : Public domain
This code is based on public domain code from Wei Dai's Crypto++ library. */
#include "Precomp.h"
#include <string.h>
#include "Sha3.h"
#include "RotateDefs.h"
#include "CpuArch.h"
#define U64C(x) UINT64_CONST(x)
static
MY_ALIGN(64)
const UInt64 SHA3_K_ARRAY[24] =
{
U64C(0x0000000000000001), U64C(0x0000000000008082),
U64C(0x800000000000808a), U64C(0x8000000080008000),
U64C(0x000000000000808b), U64C(0x0000000080000001),
U64C(0x8000000080008081), U64C(0x8000000000008009),
U64C(0x000000000000008a), U64C(0x0000000000000088),
U64C(0x0000000080008009), U64C(0x000000008000000a),
U64C(0x000000008000808b), U64C(0x800000000000008b),
U64C(0x8000000000008089), U64C(0x8000000000008003),
U64C(0x8000000000008002), U64C(0x8000000000000080),
U64C(0x000000000000800a), U64C(0x800000008000000a),
U64C(0x8000000080008081), U64C(0x8000000000008080),
U64C(0x0000000080000001), U64C(0x8000000080008008)
};
void Sha3_Init(CSha3 *p)
{
p->count = 0;
memset(p->state, 0, sizeof(p->state));
}
#define GET_state(i, a) UInt64 a = state[i];
#define SET_state(i, a) state[i] = a;
#define LS_5(M, i, a0,a1,a2,a3,a4) \
M ((i) * 5 , a0) \
M ((i) * 5 + 1, a1) \
M ((i) * 5 + 2, a2) \
M ((i) * 5 + 3, a3) \
M ((i) * 5 + 4, a4) \
#define LS_25(M) \
LS_5 (M, 0, a50, a51, a52, a53, a54) \
LS_5 (M, 1, a60, a61, a62, a63, a64) \
LS_5 (M, 2, a70, a71, a72, a73, a74) \
LS_5 (M, 3, a80, a81, a82, a83, a84) \
LS_5 (M, 4, a90, a91, a92, a93, a94) \
#define XOR_1(i, a0) \
a0 ^= GetUi64(data + (i) * 8); \
#define XOR_4(i, a0,a1,a2,a3) \
XOR_1 ((i) , a0); \
XOR_1 ((i) + 1, a1); \
XOR_1 ((i) + 2, a2); \
XOR_1 ((i) + 3, a3); \
#define D(d,b1,b2) \
d = b1 ^ Z7_ROTL64(b2, 1);
#define D5 \
D (d0, c4, c1) \
D (d1, c0, c2) \
D (d2, c1, c3) \
D (d3, c2, c4) \
D (d4, c3, c0) \
#define C0(c,a,d) \
c = a ^ d; \
#define C(c,a,d,k) \
c = a ^ d; \
c = Z7_ROTL64(c, k); \
#define E4(e1,e2,e3,e4) \
e1 = c1 ^ (~c2 & c3); \
e2 = c2 ^ (~c3 & c4); \
e3 = c3 ^ (~c4 & c0); \
e4 = c4 ^ (~c0 & c1); \
#define CK( v0,w0, \
v1,w1,k1, \
v2,w2,k2, \
v3,w3,k3, \
v4,w4,k4, e0,e1,e2,e3,e4, keccak_c) \
C0(c0,v0,w0) \
C (c1,v1,w1,k1) \
C (c2,v2,w2,k2) \
C (c3,v3,w3,k3) \
C (c4,v4,w4,k4) \
e0 = c0 ^ (~c1 & c2) ^ keccak_c; \
E4(e1,e2,e3,e4) \
#define CE( v0,w0,k0, \
v1,w1,k1, \
v2,w2,k2, \
v3,w3,k3, \
v4,w4,k4, e0,e1,e2,e3,e4) \
C (c0,v0,w0,k0) \
C (c1,v1,w1,k1) \
C (c2,v2,w2,k2) \
C (c3,v3,w3,k3) \
C (c4,v4,w4,k4) \
e0 = c0 ^ (~c1 & c2); \
E4(e1,e2,e3,e4) \
// numBlocks != 0
static
Z7_NO_INLINE
void Z7_FASTCALL Sha3_UpdateBlocks(UInt64 state[SHA3_NUM_STATE_WORDS],
const Byte *data, size_t numBlocks, size_t blockSize)
{
LS_25 (GET_state)
do
{
unsigned round;
XOR_4 ( 0, a50, a51, a52, a53)
XOR_4 ( 4, a54, a60, a61, a62)
XOR_1 ( 8, a63)
if (blockSize > 8 * 9) { XOR_4 ( 9, a64, a70, a71, a72) // sha3-384
if (blockSize > 8 * 13) { XOR_4 (13, a73, a74, a80, a81) // sha3-256
if (blockSize > 8 * 17) { XOR_1 (17, a82) // sha3-224
if (blockSize > 8 * 18) { XOR_1 (18, a83) // shake128
XOR_1 (19, a84)
XOR_1 (20, a90) }}}}
data += blockSize;
for (round = 0; round < 24; round += 2)
{
UInt64 c0, c1, c2, c3, c4;
UInt64 d0, d1, d2, d3, d4;
UInt64 e50, e51, e52, e53, e54;
UInt64 e60, e61, e62, e63, e64;
UInt64 e70, e71, e72, e73, e74;
UInt64 e80, e81, e82, e83, e84;
UInt64 e90, e91, e92, e93, e94;
c0 = a50^a60^a70^a80^a90;
c1 = a51^a61^a71^a81^a91;
c2 = a52^a62^a72^a82^a92;
c3 = a53^a63^a73^a83^a93;
c4 = a54^a64^a74^a84^a94;
D5
CK( a50, d0,
a61, d1, 44,
a72, d2, 43,
a83, d3, 21,
a94, d4, 14, e50, e51, e52, e53, e54, SHA3_K_ARRAY[round])
CE( a53, d3, 28,
a64, d4, 20,
a70, d0, 3,
a81, d1, 45,
a92, d2, 61, e60, e61, e62, e63, e64)
CE( a51, d1, 1,
a62, d2, 6,
a73, d3, 25,
a84, d4, 8,
a90, d0, 18, e70, e71, e72, e73, e74)
CE( a54, d4, 27,
a60, d0, 36,
a71, d1, 10,
a82, d2, 15,
a93, d3, 56, e80, e81, e82, e83, e84)
CE( a52, d2, 62,
a63, d3, 55,
a74, d4, 39,
a80, d0, 41,
a91, d1, 2, e90, e91, e92, e93, e94)
// ---------- ROUND + 1 ----------
c0 = e50^e60^e70^e80^e90;
c1 = e51^e61^e71^e81^e91;
c2 = e52^e62^e72^e82^e92;
c3 = e53^e63^e73^e83^e93;
c4 = e54^e64^e74^e84^e94;
D5
CK( e50, d0,
e61, d1, 44,
e72, d2, 43,
e83, d3, 21,
e94, d4, 14, a50, a51, a52, a53, a54, SHA3_K_ARRAY[(size_t)round + 1])
CE( e53, d3, 28,
e64, d4, 20,
e70, d0, 3,
e81, d1, 45,
e92, d2, 61, a60, a61, a62, a63, a64)
CE( e51, d1, 1,
e62, d2, 6,
e73, d3, 25,
e84, d4, 8,
e90, d0, 18, a70, a71, a72, a73, a74)
CE (e54, d4, 27,
e60, d0, 36,
e71, d1, 10,
e82, d2, 15,
e93, d3, 56, a80, a81, a82, a83, a84)
CE (e52, d2, 62,
e63, d3, 55,
e74, d4, 39,
e80, d0, 41,
e91, d1, 2, a90, a91, a92, a93, a94)
}
}
while (--numBlocks);
LS_25 (SET_state)
}
#define Sha3_UpdateBlock(p) \
Sha3_UpdateBlocks(p->state, p->buffer, 1, p->blockSize)
void Sha3_Update(CSha3 *p, const Byte *data, size_t size)
{
/*
for (;;)
{
if (size == 0)
return;
unsigned cur = p->blockSize - p->count;
if (cur > size)
cur = (unsigned)size;
size -= cur;
unsigned pos = p->count;
p->count = pos + cur;
while (pos & 7)
{
if (cur == 0)
return;
Byte *pb = &(((Byte *)p->state)[pos]);
*pb = (Byte)(*pb ^ *data++);
cur--;
pos++;
}
if (cur >= 8)
{
do
{
*(UInt64 *)(void *)&(((Byte *)p->state)[pos]) ^= GetUi64(data);
data += 8;
pos += 8;
cur -= 8;
}
while (cur >= 8);
}
if (pos != p->blockSize)
{
if (cur)
{
Byte *pb = &(((Byte *)p->state)[pos]);
do
{
*pb = (Byte)(*pb ^ *data++);
pb++;
}
while (--cur);
}
return;
}
Sha3_UpdateBlock(p->state);
p->count = 0;
}
*/
if (size == 0)
return;
{
const unsigned pos = p->count;
const unsigned num = p->blockSize - pos;
if (num > size)
{
p->count = pos + (unsigned)size;
memcpy(p->buffer + pos, data, size);
return;
}
if (pos != 0)
{
size -= num;
memcpy(p->buffer + pos, data, num);
data += num;
Sha3_UpdateBlock(p);
}
}
if (size >= p->blockSize)
{
const size_t numBlocks = size / p->blockSize;
const Byte *dataOld = data;
data += numBlocks * p->blockSize;
size = (size_t)(dataOld + size - data);
Sha3_UpdateBlocks(p->state, dataOld, numBlocks, p->blockSize);
}
p->count = (unsigned)size;
if (size)
memcpy(p->buffer, data, size);
}
// we support only (digestSize % 4 == 0) cases
void Sha3_Final(CSha3 *p, Byte *digest, unsigned digestSize, unsigned shake)
{
memset(p->buffer + p->count, 0, p->blockSize - p->count);
// we write bits markers from low to higher in current byte:
// - if sha-3 : 2 bits : 0,1
// - if shake : 4 bits : 1111
// then we write bit 1 to same byte.
// And we write bit 1 to highest bit of last byte of block.
p->buffer[p->count] = (Byte)(shake ? 0x1f : 0x06);
// we need xor operation (^= 0x80) here because we must write 0x80 bit
// to same byte as (0x1f : 0x06), if (p->count == p->blockSize - 1) !!!
p->buffer[p->blockSize - 1] ^= 0x80;
/*
((Byte *)p->state)[p->count] ^= (Byte)(shake ? 0x1f : 0x06);
((Byte *)p->state)[p->blockSize - 1] ^= 0x80;
*/
Sha3_UpdateBlock(p);
#if 1 && defined(MY_CPU_LE)
memcpy(digest, p->state, digestSize);
#else
{
const unsigned numWords = digestSize >> 3;
unsigned i;
for (i = 0; i < numWords; i++)
{
const UInt64 v = p->state[i];
SetUi64(digest, v)
digest += 8;
}
if (digestSize & 4) // for SHA3-224
{
const UInt32 v = (UInt32)p->state[numWords];
SetUi32(digest, v)
}
}
#endif
Sha3_Init(p);
}
#undef GET_state
#undef SET_state
#undef LS_5
#undef LS_25
#undef XOR_1
#undef XOR_4
#undef D
#undef D5
#undef C0
#undef C
#undef E4
#undef CK
#undef CE

36
C/Sha3.h Normal file
View file

@ -0,0 +1,36 @@
/* Sha3.h -- SHA-3 Hash
: Igor Pavlov : Public domain */
#ifndef ZIP7_INC_MD5_H
#define ZIP7_INC_MD5_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#define SHA3_NUM_STATE_WORDS 25
#define SHA3_BLOCK_SIZE_FROM_DIGEST_SIZE(digestSize) \
(SHA3_NUM_STATE_WORDS * 8 - (digestSize) * 2)
typedef struct
{
UInt32 count; // < blockSize
UInt32 blockSize; // <= SHA3_NUM_STATE_WORDS * 8
UInt64 _pad1[3];
// we want 32-bytes alignment here
UInt64 state[SHA3_NUM_STATE_WORDS];
UInt64 _pad2[3];
// we want 64-bytes alignment here
Byte buffer[SHA3_NUM_STATE_WORDS * 8]; // last bytes will be unused with predefined blockSize values
} CSha3;
#define Sha3_SET_blockSize(p, blockSize) { (p)->blockSize = (blockSize); }
void Sha3_Init(CSha3 *p);
void Sha3_Update(CSha3 *p, const Byte *data, size_t size);
void Sha3_Final(CSha3 *p, Byte *digest, unsigned digestSize, unsigned shake);
EXTERN_C_END
#endif

618
C/Sha512.c Normal file
View file

@ -0,0 +1,618 @@
/* Sha512.c -- SHA-512 Hash
: Igor Pavlov : Public domain
This code is based on public domain code from Wei Dai's Crypto++ library. */
#include "Precomp.h"
#include <string.h>
#include "Sha512.h"
#include "RotateDefs.h"
#include "CpuArch.h"
#ifdef MY_CPU_X86_OR_AMD64
#if defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 170001) \
|| defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 170001) \
|| defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 140000) \
|| defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 2400) && (__INTEL_COMPILER <= 9900) \
|| defined(_MSC_VER) && (_MSC_VER >= 1940)
#define Z7_COMPILER_SHA512_SUPPORTED
#endif
#elif defined(MY_CPU_ARM64) && defined(MY_CPU_LE)
#if defined(__ARM_FEATURE_SHA512)
#define Z7_COMPILER_SHA512_SUPPORTED
#else
#if (defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 130000) \
|| defined(__GNUC__) && (__GNUC__ >= 9) \
) \
|| defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1940) // fix it
#define Z7_COMPILER_SHA512_SUPPORTED
#endif
#endif
#endif
void Z7_FASTCALL Sha512_UpdateBlocks(UInt64 state[8], const Byte *data, size_t numBlocks);
#ifdef Z7_COMPILER_SHA512_SUPPORTED
void Z7_FASTCALL Sha512_UpdateBlocks_HW(UInt64 state[8], const Byte *data, size_t numBlocks);
static SHA512_FUNC_UPDATE_BLOCKS g_SHA512_FUNC_UPDATE_BLOCKS = Sha512_UpdateBlocks;
static SHA512_FUNC_UPDATE_BLOCKS g_SHA512_FUNC_UPDATE_BLOCKS_HW;
#define SHA512_UPDATE_BLOCKS(p) p->v.vars.func_UpdateBlocks
#else
#define SHA512_UPDATE_BLOCKS(p) Sha512_UpdateBlocks
#endif
BoolInt Sha512_SetFunction(CSha512 *p, unsigned algo)
{
SHA512_FUNC_UPDATE_BLOCKS func = Sha512_UpdateBlocks;
#ifdef Z7_COMPILER_SHA512_SUPPORTED
if (algo != SHA512_ALGO_SW)
{
if (algo == SHA512_ALGO_DEFAULT)
func = g_SHA512_FUNC_UPDATE_BLOCKS;
else
{
if (algo != SHA512_ALGO_HW)
return False;
func = g_SHA512_FUNC_UPDATE_BLOCKS_HW;
if (!func)
return False;
}
}
#else
if (algo > 1)
return False;
#endif
p->v.vars.func_UpdateBlocks = func;
return True;
}
/* define it for speed optimization */
#if 0 // 1 for size optimization
#define STEP_PRE 1
#define STEP_MAIN 1
#else
#define STEP_PRE 2
#define STEP_MAIN 4
// #define Z7_SHA512_UNROLL
#endif
#undef Z7_SHA512_BIG_W
#if STEP_MAIN != 16
#define Z7_SHA512_BIG_W
#endif
#define U64C(x) UINT64_CONST(x)
static MY_ALIGN(64) const UInt64 SHA512_INIT_ARRAYS[4][8] = {
{ U64C(0x8c3d37c819544da2), U64C(0x73e1996689dcd4d6), U64C(0x1dfab7ae32ff9c82), U64C(0x679dd514582f9fcf),
U64C(0x0f6d2b697bd44da8), U64C(0x77e36f7304c48942), U64C(0x3f9d85a86a1d36c8), U64C(0x1112e6ad91d692a1)
},
{ U64C(0x22312194fc2bf72c), U64C(0x9f555fa3c84c64c2), U64C(0x2393b86b6f53b151), U64C(0x963877195940eabd),
U64C(0x96283ee2a88effe3), U64C(0xbe5e1e2553863992), U64C(0x2b0199fc2c85b8aa), U64C(0x0eb72ddc81c52ca2)
},
{ U64C(0xcbbb9d5dc1059ed8), U64C(0x629a292a367cd507), U64C(0x9159015a3070dd17), U64C(0x152fecd8f70e5939),
U64C(0x67332667ffc00b31), U64C(0x8eb44a8768581511), U64C(0xdb0c2e0d64f98fa7), U64C(0x47b5481dbefa4fa4)
},
{ U64C(0x6a09e667f3bcc908), U64C(0xbb67ae8584caa73b), U64C(0x3c6ef372fe94f82b), U64C(0xa54ff53a5f1d36f1),
U64C(0x510e527fade682d1), U64C(0x9b05688c2b3e6c1f), U64C(0x1f83d9abfb41bd6b), U64C(0x5be0cd19137e2179)
}};
void Sha512_InitState(CSha512 *p, unsigned digestSize)
{
p->v.vars.count = 0;
memcpy(p->state, SHA512_INIT_ARRAYS[(size_t)(digestSize >> 4) - 1], sizeof(p->state));
}
void Sha512_Init(CSha512 *p, unsigned digestSize)
{
p->v.vars.func_UpdateBlocks =
#ifdef Z7_COMPILER_SHA512_SUPPORTED
g_SHA512_FUNC_UPDATE_BLOCKS;
#else
NULL;
#endif
Sha512_InitState(p, digestSize);
}
#define S0(x) (Z7_ROTR64(x,28) ^ Z7_ROTR64(x,34) ^ Z7_ROTR64(x,39))
#define S1(x) (Z7_ROTR64(x,14) ^ Z7_ROTR64(x,18) ^ Z7_ROTR64(x,41))
#define s0(x) (Z7_ROTR64(x, 1) ^ Z7_ROTR64(x, 8) ^ (x >> 7))
#define s1(x) (Z7_ROTR64(x,19) ^ Z7_ROTR64(x,61) ^ (x >> 6))
#define Ch(x,y,z) (z^(x&(y^z)))
#define Maj(x,y,z) ((x&y)|(z&(x|y)))
#define W_PRE(i) (W[(i) + (size_t)(j)] = GetBe64(data + ((size_t)(j) + i) * 8))
#define blk2_main(j, i) s1(w(j, (i)-2)) + w(j, (i)-7) + s0(w(j, (i)-15))
#ifdef Z7_SHA512_BIG_W
// we use +i instead of +(i) to change the order to solve CLANG compiler warning for signed/unsigned.
#define w(j, i) W[(size_t)(j) + i]
#define blk2(j, i) (w(j, i) = w(j, (i)-16) + blk2_main(j, i))
#else
#if STEP_MAIN == 16
#define w(j, i) W[(i) & 15]
#else
#define w(j, i) W[((size_t)(j) + (i)) & 15]
#endif
#define blk2(j, i) (w(j, i) += blk2_main(j, i))
#endif
#define W_MAIN(i) blk2(j, i)
#define T1(wx, i) \
tmp = h + S1(e) + Ch(e,f,g) + K[(i)+(size_t)(j)] + wx(i); \
h = g; \
g = f; \
f = e; \
e = d + tmp; \
tmp += S0(a) + Maj(a, b, c); \
d = c; \
c = b; \
b = a; \
a = tmp; \
#define R1_PRE(i) T1( W_PRE, i)
#define R1_MAIN(i) T1( W_MAIN, i)
#if (!defined(Z7_SHA512_UNROLL) || STEP_MAIN < 8) && (STEP_MAIN >= 4)
#define R2_MAIN(i) \
R1_MAIN(i) \
R1_MAIN(i + 1) \
#endif
#if defined(Z7_SHA512_UNROLL) && STEP_MAIN >= 8
#define T4( a,b,c,d,e,f,g,h, wx, i) \
h += S1(e) + Ch(e,f,g) + K[(i)+(size_t)(j)] + wx(i); \
tmp = h; \
h += d; \
d = tmp + S0(a) + Maj(a, b, c); \
#define R4( wx, i) \
T4 ( a,b,c,d,e,f,g,h, wx, (i )); \
T4 ( d,a,b,c,h,e,f,g, wx, (i+1)); \
T4 ( c,d,a,b,g,h,e,f, wx, (i+2)); \
T4 ( b,c,d,a,f,g,h,e, wx, (i+3)); \
#define R4_PRE(i) R4( W_PRE, i)
#define R4_MAIN(i) R4( W_MAIN, i)
#define T8( a,b,c,d,e,f,g,h, wx, i) \
h += S1(e) + Ch(e,f,g) + K[(i)+(size_t)(j)] + wx(i); \
d += h; \
h += S0(a) + Maj(a, b, c); \
#define R8( wx, i) \
T8 ( a,b,c,d,e,f,g,h, wx, i ); \
T8 ( h,a,b,c,d,e,f,g, wx, i+1); \
T8 ( g,h,a,b,c,d,e,f, wx, i+2); \
T8 ( f,g,h,a,b,c,d,e, wx, i+3); \
T8 ( e,f,g,h,a,b,c,d, wx, i+4); \
T8 ( d,e,f,g,h,a,b,c, wx, i+5); \
T8 ( c,d,e,f,g,h,a,b, wx, i+6); \
T8 ( b,c,d,e,f,g,h,a, wx, i+7); \
#define R8_PRE(i) R8( W_PRE, i)
#define R8_MAIN(i) R8( W_MAIN, i)
#endif
extern
MY_ALIGN(64) const UInt64 SHA512_K_ARRAY[80];
MY_ALIGN(64) const UInt64 SHA512_K_ARRAY[80] = {
U64C(0x428a2f98d728ae22), U64C(0x7137449123ef65cd), U64C(0xb5c0fbcfec4d3b2f), U64C(0xe9b5dba58189dbbc),
U64C(0x3956c25bf348b538), U64C(0x59f111f1b605d019), U64C(0x923f82a4af194f9b), U64C(0xab1c5ed5da6d8118),
U64C(0xd807aa98a3030242), U64C(0x12835b0145706fbe), U64C(0x243185be4ee4b28c), U64C(0x550c7dc3d5ffb4e2),
U64C(0x72be5d74f27b896f), U64C(0x80deb1fe3b1696b1), U64C(0x9bdc06a725c71235), U64C(0xc19bf174cf692694),
U64C(0xe49b69c19ef14ad2), U64C(0xefbe4786384f25e3), U64C(0x0fc19dc68b8cd5b5), U64C(0x240ca1cc77ac9c65),
U64C(0x2de92c6f592b0275), U64C(0x4a7484aa6ea6e483), U64C(0x5cb0a9dcbd41fbd4), U64C(0x76f988da831153b5),
U64C(0x983e5152ee66dfab), U64C(0xa831c66d2db43210), U64C(0xb00327c898fb213f), U64C(0xbf597fc7beef0ee4),
U64C(0xc6e00bf33da88fc2), U64C(0xd5a79147930aa725), U64C(0x06ca6351e003826f), U64C(0x142929670a0e6e70),
U64C(0x27b70a8546d22ffc), U64C(0x2e1b21385c26c926), U64C(0x4d2c6dfc5ac42aed), U64C(0x53380d139d95b3df),
U64C(0x650a73548baf63de), U64C(0x766a0abb3c77b2a8), U64C(0x81c2c92e47edaee6), U64C(0x92722c851482353b),
U64C(0xa2bfe8a14cf10364), U64C(0xa81a664bbc423001), U64C(0xc24b8b70d0f89791), U64C(0xc76c51a30654be30),
U64C(0xd192e819d6ef5218), U64C(0xd69906245565a910), U64C(0xf40e35855771202a), U64C(0x106aa07032bbd1b8),
U64C(0x19a4c116b8d2d0c8), U64C(0x1e376c085141ab53), U64C(0x2748774cdf8eeb99), U64C(0x34b0bcb5e19b48a8),
U64C(0x391c0cb3c5c95a63), U64C(0x4ed8aa4ae3418acb), U64C(0x5b9cca4f7763e373), U64C(0x682e6ff3d6b2b8a3),
U64C(0x748f82ee5defb2fc), U64C(0x78a5636f43172f60), U64C(0x84c87814a1f0ab72), U64C(0x8cc702081a6439ec),
U64C(0x90befffa23631e28), U64C(0xa4506cebde82bde9), U64C(0xbef9a3f7b2c67915), U64C(0xc67178f2e372532b),
U64C(0xca273eceea26619c), U64C(0xd186b8c721c0c207), U64C(0xeada7dd6cde0eb1e), U64C(0xf57d4f7fee6ed178),
U64C(0x06f067aa72176fba), U64C(0x0a637dc5a2c898a6), U64C(0x113f9804bef90dae), U64C(0x1b710b35131c471b),
U64C(0x28db77f523047d84), U64C(0x32caab7b40c72493), U64C(0x3c9ebe0a15c9bebc), U64C(0x431d67c49c100d4c),
U64C(0x4cc5d4becb3e42b6), U64C(0x597f299cfc657e2a), U64C(0x5fcb6fab3ad6faec), U64C(0x6c44198c4a475817)
};
#define K SHA512_K_ARRAY
Z7_NO_INLINE
void Z7_FASTCALL Sha512_UpdateBlocks(UInt64 state[8], const Byte *data, size_t numBlocks)
{
UInt64 W
#ifdef Z7_SHA512_BIG_W
[80];
#else
[16];
#endif
unsigned j;
UInt64 a,b,c,d,e,f,g,h;
#if !defined(Z7_SHA512_UNROLL) || (STEP_MAIN <= 4) || (STEP_PRE <= 4)
UInt64 tmp;
#endif
if (numBlocks == 0) return;
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
f = state[5];
g = state[6];
h = state[7];
do
{
for (j = 0; j < 16; j += STEP_PRE)
{
#if STEP_PRE > 4
#if STEP_PRE < 8
R4_PRE(0);
#else
R8_PRE(0);
#if STEP_PRE == 16
R8_PRE(8);
#endif
#endif
#else
R1_PRE(0)
#if STEP_PRE >= 2
R1_PRE(1)
#if STEP_PRE >= 4
R1_PRE(2)
R1_PRE(3)
#endif
#endif
#endif
}
for (j = 16; j < 80; j += STEP_MAIN)
{
#if defined(Z7_SHA512_UNROLL) && STEP_MAIN >= 8
#if STEP_MAIN < 8
R4_MAIN(0)
#else
R8_MAIN(0)
#if STEP_MAIN == 16
R8_MAIN(8)
#endif
#endif
#else
R1_MAIN(0)
#if STEP_MAIN >= 2
R1_MAIN(1)
#if STEP_MAIN >= 4
R2_MAIN(2)
#if STEP_MAIN >= 8
R2_MAIN(4)
R2_MAIN(6)
#if STEP_MAIN >= 16
R2_MAIN(8)
R2_MAIN(10)
R2_MAIN(12)
R2_MAIN(14)
#endif
#endif
#endif
#endif
#endif
}
a += state[0]; state[0] = a;
b += state[1]; state[1] = b;
c += state[2]; state[2] = c;
d += state[3]; state[3] = d;
e += state[4]; state[4] = e;
f += state[5]; state[5] = f;
g += state[6]; state[6] = g;
h += state[7]; state[7] = h;
data += SHA512_BLOCK_SIZE;
}
while (--numBlocks);
}
#define Sha512_UpdateBlock(p) SHA512_UPDATE_BLOCKS(p)(p->state, p->buffer, 1)
void Sha512_Update(CSha512 *p, const Byte *data, size_t size)
{
if (size == 0)
return;
{
const unsigned pos = (unsigned)p->v.vars.count & (SHA512_BLOCK_SIZE - 1);
const unsigned num = SHA512_BLOCK_SIZE - pos;
p->v.vars.count += size;
if (num > size)
{
memcpy(p->buffer + pos, data, size);
return;
}
if (pos != 0)
{
size -= num;
memcpy(p->buffer + pos, data, num);
data += num;
Sha512_UpdateBlock(p);
}
}
{
const size_t numBlocks = size >> 7;
// if (numBlocks)
SHA512_UPDATE_BLOCKS(p)(p->state, data, numBlocks);
size &= SHA512_BLOCK_SIZE - 1;
if (size == 0)
return;
data += (numBlocks << 7);
memcpy(p->buffer, data, size);
}
}
void Sha512_Final(CSha512 *p, Byte *digest, unsigned digestSize)
{
unsigned pos = (unsigned)p->v.vars.count & (SHA512_BLOCK_SIZE - 1);
p->buffer[pos++] = 0x80;
if (pos > (SHA512_BLOCK_SIZE - 8 * 2))
{
while (pos != SHA512_BLOCK_SIZE) { p->buffer[pos++] = 0; }
// memset(&p->buf.buffer[pos], 0, SHA512_BLOCK_SIZE - pos);
Sha512_UpdateBlock(p);
pos = 0;
}
memset(&p->buffer[pos], 0, (SHA512_BLOCK_SIZE - 8 * 2) - pos);
{
const UInt64 numBits = p->v.vars.count << 3;
SetBe64(p->buffer + SHA512_BLOCK_SIZE - 8 * 2, 0) // = (p->v.vars.count >> (64 - 3)); (high 64-bits)
SetBe64(p->buffer + SHA512_BLOCK_SIZE - 8 * 1, numBits)
}
Sha512_UpdateBlock(p);
#if 1 && defined(MY_CPU_BE)
memcpy(digest, p->state, digestSize);
#else
{
const unsigned numWords = digestSize >> 3;
unsigned i;
for (i = 0; i < numWords; i++)
{
const UInt64 v = p->state[i];
SetBe64(digest, v)
digest += 8;
}
if (digestSize & 4) // digestSize == SHA512_224_DIGEST_SIZE
{
const UInt32 v = (UInt32)((p->state[numWords]) >> 32);
SetBe32(digest, v)
}
}
#endif
Sha512_InitState(p, digestSize);
}
#if defined(_WIN32) && defined(Z7_COMPILER_SHA512_SUPPORTED) \
&& defined(MY_CPU_ARM64) // we can disable this check to debug in x64
#if 1 // 0 for debug
#include "7zWindows.h"
// #include <stdio.h>
#if 0 && defined(MY_CPU_X86_OR_AMD64)
#include <intrin.h> // for debug : for __ud2()
#endif
BoolInt CPU_IsSupported_SHA512(void)
{
#if defined(MY_CPU_ARM64)
// we have no SHA512 flag for IsProcessorFeaturePresent() still.
if (!CPU_IsSupported_CRYPTO())
return False;
#endif
// printf("\nCPU_IsSupported_SHA512\n");
{
// we can't read ID_AA64ISAR0_EL1 register from application.
// but ID_AA64ISAR0_EL1 register is mapped to "CP 4030" registry value.
HKEY key = NULL;
LONG res = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"),
0, KEY_READ, &key);
if (res != ERROR_SUCCESS)
return False;
{
DWORD type = 0;
DWORD count = sizeof(UInt64);
UInt64 val = 0;
res = RegQueryValueEx(key, TEXT("CP 4030"), NULL,
&type, (LPBYTE)&val, &count);
RegCloseKey(key);
if (res != ERROR_SUCCESS
|| type != REG_QWORD
|| count != sizeof(UInt64)
|| ((unsigned)(val >> 12) & 0xf) != 2)
return False;
// we parse SHA2 field of ID_AA64ISAR0_EL1 register:
// 0 : No SHA2 instructions implemented
// 1 : SHA256 implemented
// 2 : SHA256 and SHA512 implemented
}
}
#if 1 // 0 for debug to disable SHA512 PROBE code
/*
----- SHA512 PROBE -----
We suppose that "CP 4030" registry reading is enough.
But we use additional SHA512 PROBE code, because
we can catch exception here, and we don't catch exceptions,
if we call Sha512 functions from main code.
NOTE: arm64 PROBE code doesn't work, if we call it via Wine in linux-arm64.
The program just stops.
Also x64 version of PROBE code doesn't work, if we run it via Intel SDE emulator
without SHA512 support (-skl switch),
The program stops, and we have message from SDE:
TID 0 SDE-ERROR: Executed instruction not valid for specified chip (SKYLAKE): vsha512msg1
But we still want to catch that exception instead of process stopping.
Does this PROBE code work in native Windows-arm64 (with/without sha512 hw instructions)?
Are there any ways to fix the problems with arm64-wine and x64-SDE cases?
*/
// printf("\n========== CPU_IsSupported_SHA512 PROBE ========\n");
{
#ifdef __clang_major__
#pragma GCC diagnostic ignored "-Wlanguage-extension-token"
#endif
__try
{
#if 0 // 1 : for debug (reduced version to detect sha512)
const uint64x2_t a = vdupq_n_u64(1);
const uint64x2_t b = vsha512hq_u64(a, a, a);
if ((UInt32)vgetq_lane_u64(b, 0) == 0x11800002)
return True;
#else
MY_ALIGN(16)
UInt64 temp[SHA512_NUM_DIGEST_WORDS + SHA512_NUM_BLOCK_WORDS];
memset(temp, 0x5a, sizeof(temp));
#if 0 && defined(MY_CPU_X86_OR_AMD64)
__ud2(); // for debug : that exception is not problem for SDE
#endif
#if 1
Sha512_UpdateBlocks_HW(temp,
(const Byte *)(const void *)(temp + SHA512_NUM_DIGEST_WORDS), 1);
// printf("\n==== t = %x\n", (UInt32)temp[0]);
if ((UInt32)temp[0] == 0xa33cfdf7)
{
// printf("\n=== PROBE SHA512: SHA512 supported\n");
return True;
}
#endif
#endif
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
// printf("\n==== CPU_IsSupported_SHA512 EXCEPTION_EXECUTE_HANDLER\n");
}
}
return False;
#else
// without SHA512 PROBE code
return True;
#endif
}
#else
BoolInt CPU_IsSupported_SHA512(void)
{
return False;
}
#endif
#endif // WIN32 arm64
void Sha512Prepare(void)
{
#ifdef Z7_COMPILER_SHA512_SUPPORTED
SHA512_FUNC_UPDATE_BLOCKS f, f_hw;
f = Sha512_UpdateBlocks;
f_hw = NULL;
#ifdef MY_CPU_X86_OR_AMD64
if (CPU_IsSupported_SHA512()
&& CPU_IsSupported_AVX2()
)
#else
if (CPU_IsSupported_SHA512())
#endif
{
// printf("\n========== HW SHA512 ======== \n");
f = f_hw = Sha512_UpdateBlocks_HW;
}
g_SHA512_FUNC_UPDATE_BLOCKS = f;
g_SHA512_FUNC_UPDATE_BLOCKS_HW = f_hw;
#endif
}
#undef K
#undef S0
#undef S1
#undef s0
#undef s1
#undef Ch
#undef Maj
#undef W_MAIN
#undef W_PRE
#undef w
#undef blk2_main
#undef blk2
#undef T1
#undef T4
#undef T8
#undef R1_PRE
#undef R1_MAIN
#undef R2_MAIN
#undef R4
#undef R4_PRE
#undef R4_MAIN
#undef R8
#undef R8_PRE
#undef R8_MAIN
#undef STEP_PRE
#undef STEP_MAIN
#undef Z7_SHA512_BIG_W
#undef Z7_SHA512_UNROLL
#undef Z7_COMPILER_SHA512_SUPPORTED

86
C/Sha512.h Normal file
View file

@ -0,0 +1,86 @@
/* Sha512.h -- SHA-512 Hash
: Igor Pavlov : Public domain */
#ifndef ZIP7_INC_SHA512_H
#define ZIP7_INC_SHA512_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#define SHA512_NUM_BLOCK_WORDS 16
#define SHA512_NUM_DIGEST_WORDS 8
#define SHA512_BLOCK_SIZE (SHA512_NUM_BLOCK_WORDS * 8)
#define SHA512_DIGEST_SIZE (SHA512_NUM_DIGEST_WORDS * 8)
#define SHA512_224_DIGEST_SIZE (224 / 8)
#define SHA512_256_DIGEST_SIZE (256 / 8)
#define SHA512_384_DIGEST_SIZE (384 / 8)
typedef void (Z7_FASTCALL *SHA512_FUNC_UPDATE_BLOCKS)(UInt64 state[8], const Byte *data, size_t numBlocks);
/*
if (the system supports different SHA512 code implementations)
{
(CSha512::func_UpdateBlocks) will be used
(CSha512::func_UpdateBlocks) can be set by
Sha512_Init() - to default (fastest)
Sha512_SetFunction() - to any algo
}
else
{
(CSha512::func_UpdateBlocks) is ignored.
}
*/
typedef struct
{
union
{
struct
{
SHA512_FUNC_UPDATE_BLOCKS func_UpdateBlocks;
UInt64 count;
} vars;
UInt64 _pad_64bit[8];
void *_pad_align_ptr[2];
} v;
UInt64 state[SHA512_NUM_DIGEST_WORDS];
Byte buffer[SHA512_BLOCK_SIZE];
} CSha512;
#define SHA512_ALGO_DEFAULT 0
#define SHA512_ALGO_SW 1
#define SHA512_ALGO_HW 2
/*
Sha512_SetFunction()
return:
0 - (algo) value is not supported, and func_UpdateBlocks was not changed
1 - func_UpdateBlocks was set according (algo) value.
*/
BoolInt Sha512_SetFunction(CSha512 *p, unsigned algo);
// we support only these (digestSize) values: 224/8, 256/8, 384/8, 512/8
void Sha512_InitState(CSha512 *p, unsigned digestSize);
void Sha512_Init(CSha512 *p, unsigned digestSize);
void Sha512_Update(CSha512 *p, const Byte *data, size_t size);
void Sha512_Final(CSha512 *p, Byte *digest, unsigned digestSize);
// void Z7_FASTCALL Sha512_UpdateBlocks(UInt64 state[8], const Byte *data, size_t numBlocks);
/*
call Sha512Prepare() once at program start.
It prepares all supported implementations, and detects the fastest implementation.
*/
void Sha512Prepare(void);
EXTERN_C_END
#endif

395
C/Sha512Opt.c Normal file
View file

@ -0,0 +1,395 @@
/* Sha512Opt.c -- SHA-512 optimized code for SHA-512 hardware instructions
: Igor Pavlov : Public domain */
#include "Precomp.h"
#include "Compiler.h"
#include "CpuArch.h"
// #define Z7_USE_HW_SHA_STUB // for debug
#ifdef MY_CPU_X86_OR_AMD64
#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 2400) && (__INTEL_COMPILER <= 9900) // fix it
#define USE_HW_SHA
#elif defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 170001) \
|| defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 170001) \
|| defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 140000)
#define USE_HW_SHA
#if !defined(__INTEL_COMPILER)
// icc defines __GNUC__, but icc doesn't support __attribute__(__target__)
#if !defined(__SHA512__) || !defined(__AVX2__)
#define ATTRIB_SHA512 __attribute__((__target__("sha512,avx2")))
#endif
#endif
#elif defined(Z7_MSC_VER_ORIGINAL)
#if (_MSC_VER >= 1940)
#define USE_HW_SHA
#else
// #define Z7_USE_HW_SHA_STUB
#endif
#endif
// #endif // MY_CPU_X86_OR_AMD64
#ifndef USE_HW_SHA
// #define Z7_USE_HW_SHA_STUB // for debug
#endif
#ifdef USE_HW_SHA
// #pragma message("Sha512 HW")
#include <immintrin.h>
#if defined (__clang__) && defined(_MSC_VER)
#if !defined(__AVX__)
#include <avxintrin.h>
#endif
#if !defined(__AVX2__)
#include <avx2intrin.h>
#endif
#if !defined(__SHA512__)
#include <sha512intrin.h>
#endif
#else
#endif
/*
SHA512 uses:
AVX:
_mm256_loadu_si256 (vmovdqu)
_mm256_storeu_si256
_mm256_set_epi32 (unused)
AVX2:
_mm256_add_epi64 : vpaddq
_mm256_shuffle_epi8 : vpshufb
_mm256_shuffle_epi32 : pshufd
_mm256_blend_epi32 : vpblendd
_mm256_permute4x64_epi64 : vpermq : 3c
_mm256_permute2x128_si256: vperm2i128 : 3c
_mm256_extracti128_si256 : vextracti128 : 3c
SHA512:
_mm256_sha512*
*/
// K array must be aligned for 32-bytes at least.
// The compiler can look align attribute and selects
// vmovdqu - for code without align attribute
// vmovdqa - for code with align attribute
extern
MY_ALIGN(64)
const UInt64 SHA512_K_ARRAY[80];
#define K SHA512_K_ARRAY
#define ADD_EPI64(dest, src) dest = _mm256_add_epi64(dest, src);
#define SHA512_MSG1(dest, src) dest = _mm256_sha512msg1_epi64(dest, _mm256_extracti128_si256(src, 0));
#define SHA512_MSG2(dest, src) dest = _mm256_sha512msg2_epi64(dest, src);
#define LOAD_SHUFFLE(m, k) \
m = _mm256_loadu_si256((const __m256i *)(const void *)(data + (k) * 32)); \
m = _mm256_shuffle_epi8(m, mask); \
#define NNN(m0, m1, m2, m3)
#define SM1(m1, m2, m3, m0) \
SHA512_MSG1(m0, m1); \
#define SM2(m2, m3, m0, m1) \
ADD_EPI64(m0, _mm256_permute4x64_epi64(_mm256_blend_epi32(m2, m3, 3), 0x39)); \
SHA512_MSG2(m0, m3); \
#define RND2(t0, t1, lane) \
t0 = _mm256_sha512rnds2_epi64(t0, t1, _mm256_extracti128_si256(msg, lane));
#define R4(k, m0, m1, m2, m3, OP0, OP1) \
msg = _mm256_add_epi64(m0, *(const __m256i *) (const void *) &K[(k) * 4]); \
RND2(state0, state1, 0); OP0(m0, m1, m2, m3) \
RND2(state1, state0, 1); OP1(m0, m1, m2, m3) \
#define R16(k, OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7) \
R4 ( (k)*4+0, m0,m1,m2,m3, OP0, OP1 ) \
R4 ( (k)*4+1, m1,m2,m3,m0, OP2, OP3 ) \
R4 ( (k)*4+2, m2,m3,m0,m1, OP4, OP5 ) \
R4 ( (k)*4+3, m3,m0,m1,m2, OP6, OP7 ) \
#define PREPARE_STATE \
state0 = _mm256_shuffle_epi32(state0, 0x4e); /* cdab */ \
state1 = _mm256_shuffle_epi32(state1, 0x4e); /* ghef */ \
tmp = state0; \
state0 = _mm256_permute2x128_si256(state0, state1, 0x13); /* cdgh */ \
state1 = _mm256_permute2x128_si256(tmp, state1, 2); /* abef */ \
void Z7_FASTCALL Sha512_UpdateBlocks_HW(UInt64 state[8], const Byte *data, size_t numBlocks);
#ifdef ATTRIB_SHA512
ATTRIB_SHA512
#endif
void Z7_FASTCALL Sha512_UpdateBlocks_HW(UInt64 state[8], const Byte *data, size_t numBlocks)
{
const __m256i mask = _mm256_set_epi32(
0x08090a0b,0x0c0d0e0f, 0x00010203,0x04050607,
0x08090a0b,0x0c0d0e0f, 0x00010203,0x04050607);
__m256i tmp, state0, state1;
if (numBlocks == 0)
return;
state0 = _mm256_loadu_si256((const __m256i *) (const void *) &state[0]);
state1 = _mm256_loadu_si256((const __m256i *) (const void *) &state[4]);
PREPARE_STATE
do
{
__m256i state0_save, state1_save;
__m256i m0, m1, m2, m3;
__m256i msg;
// #define msg tmp
state0_save = state0;
state1_save = state1;
LOAD_SHUFFLE (m0, 0)
LOAD_SHUFFLE (m1, 1)
LOAD_SHUFFLE (m2, 2)
LOAD_SHUFFLE (m3, 3)
R16 ( 0, NNN, NNN, SM1, NNN, SM1, SM2, SM1, SM2 )
R16 ( 1, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 )
R16 ( 2, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 )
R16 ( 3, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 )
R16 ( 4, SM1, SM2, NNN, SM2, NNN, NNN, NNN, NNN )
ADD_EPI64(state0, state0_save)
ADD_EPI64(state1, state1_save)
data += 128;
}
while (--numBlocks);
PREPARE_STATE
_mm256_storeu_si256((__m256i *) (void *) &state[0], state0);
_mm256_storeu_si256((__m256i *) (void *) &state[4], state1);
}
#endif // USE_HW_SHA
// gcc 8.5 also supports sha512, but we need also support in assembler that is called by gcc
#elif defined(MY_CPU_ARM64) && defined(MY_CPU_LE)
#if defined(__ARM_FEATURE_SHA512)
#define USE_HW_SHA
#else
#if (defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 130000) \
|| defined(__GNUC__) && (__GNUC__ >= 9) \
) \
|| defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1940) // fix it
#define USE_HW_SHA
#endif
#endif
#ifdef USE_HW_SHA
// #pragma message("=== Sha512 HW === ")
#if defined(__clang__) || defined(__GNUC__)
#if !defined(__ARM_FEATURE_SHA512)
// #pragma message("=== we define SHA3 ATTRIB_SHA512 === ")
#if defined(__clang__)
#define ATTRIB_SHA512 __attribute__((__target__("sha3"))) // "armv8.2-a,sha3"
#else
#define ATTRIB_SHA512 __attribute__((__target__("arch=armv8.2-a+sha3")))
#endif
#endif
#endif
#if defined(Z7_MSC_VER_ORIGINAL)
#include <arm64_neon.h>
#else
#if defined(__clang__) && __clang_major__ < 16
#if !defined(__ARM_FEATURE_SHA512)
// #pragma message("=== we set __ARM_FEATURE_SHA512 1 === ")
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
#define Z7_ARM_FEATURE_SHA512_WAS_SET 1
#define __ARM_FEATURE_SHA512 1
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
#endif
#endif // clang
#include <arm_neon.h>
#if defined(Z7_ARM_FEATURE_SHA512_WAS_SET) && \
defined(__ARM_FEATURE_SHA512)
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
#undef __ARM_FEATURE_SHA512
#undef Z7_ARM_FEATURE_SHA512_WAS_SET
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
// #pragma message("=== we undefine __ARM_FEATURE_CRYPTO === ")
#endif
#endif // Z7_MSC_VER_ORIGINAL
typedef uint64x2_t v128_64;
// typedef __n128 v128_64; // MSVC
#ifdef MY_CPU_BE
#define MY_rev64_for_LE(x) x
#else
#define MY_rev64_for_LE(x) vrev64q_u8(x)
#endif
#define LOAD_128_64(_p) vld1q_u64(_p)
#define LOAD_128_8(_p) vld1q_u8 (_p)
#define STORE_128_64(_p, _v) vst1q_u64(_p, _v)
#define LOAD_SHUFFLE(m, k) \
m = vreinterpretq_u64_u8( \
MY_rev64_for_LE( \
LOAD_128_8(data + (k) * 16))); \
// K array must be aligned for 16-bytes at least.
extern
MY_ALIGN(64)
const UInt64 SHA512_K_ARRAY[80];
#define K SHA512_K_ARRAY
#define NN(m0, m1, m4, m5, m7)
#define SM(m0, m1, m4, m5, m7) \
m0 = vsha512su1q_u64(vsha512su0q_u64(m0, m1), m7, vextq_u64(m4, m5, 1));
#define R2(k, m0,m1,m2,m3,m4,m5,m6,m7, a0,a1,a2,a3, OP) \
OP(m0, m1, m4, m5, m7) \
t = vaddq_u64(m0, vld1q_u64(k)); \
t = vaddq_u64(vextq_u64(t, t, 1), a3); \
t = vsha512hq_u64(t, vextq_u64(a2, a3, 1), vextq_u64(a1, a2, 1)); \
a3 = vsha512h2q_u64(t, a1, a0); \
a1 = vaddq_u64(a1, t); \
#define R8(k, m0,m1,m2,m3,m4,m5,m6,m7, OP) \
R2 ( (k)+0*2, m0,m1,m2,m3,m4,m5,m6,m7, a0,a1,a2,a3, OP ) \
R2 ( (k)+1*2, m1,m2,m3,m4,m5,m6,m7,m0, a3,a0,a1,a2, OP ) \
R2 ( (k)+2*2, m2,m3,m4,m5,m6,m7,m0,m1, a2,a3,a0,a1, OP ) \
R2 ( (k)+3*2, m3,m4,m5,m6,m7,m0,m1,m2, a1,a2,a3,a0, OP ) \
#define R16(k, OP) \
R8 ( (k)+0*2, m0,m1,m2,m3,m4,m5,m6,m7, OP ) \
R8 ( (k)+4*2, m4,m5,m6,m7,m0,m1,m2,m3, OP ) \
void Z7_FASTCALL Sha512_UpdateBlocks_HW(UInt64 state[8], const Byte *data, size_t numBlocks);
#ifdef ATTRIB_SHA512
ATTRIB_SHA512
#endif
void Z7_FASTCALL Sha512_UpdateBlocks_HW(UInt64 state[8], const Byte *data, size_t numBlocks)
{
v128_64 a0, a1, a2, a3;
if (numBlocks == 0)
return;
a0 = LOAD_128_64(&state[0]);
a1 = LOAD_128_64(&state[2]);
a2 = LOAD_128_64(&state[4]);
a3 = LOAD_128_64(&state[6]);
do
{
v128_64 a0_save, a1_save, a2_save, a3_save;
v128_64 m0, m1, m2, m3, m4, m5, m6, m7;
v128_64 t;
unsigned i;
const UInt64 *k_ptr;
LOAD_SHUFFLE (m0, 0)
LOAD_SHUFFLE (m1, 1)
LOAD_SHUFFLE (m2, 2)
LOAD_SHUFFLE (m3, 3)
LOAD_SHUFFLE (m4, 4)
LOAD_SHUFFLE (m5, 5)
LOAD_SHUFFLE (m6, 6)
LOAD_SHUFFLE (m7, 7)
a0_save = a0;
a1_save = a1;
a2_save = a2;
a3_save = a3;
R16 ( K, NN )
k_ptr = K + 16;
for (i = 0; i < 4; i++)
{
R16 ( k_ptr, SM )
k_ptr += 16;
}
a0 = vaddq_u64(a0, a0_save);
a1 = vaddq_u64(a1, a1_save);
a2 = vaddq_u64(a2, a2_save);
a3 = vaddq_u64(a3, a3_save);
data += 128;
}
while (--numBlocks);
STORE_128_64(&state[0], a0);
STORE_128_64(&state[2], a1);
STORE_128_64(&state[4], a2);
STORE_128_64(&state[6], a3);
}
#endif // USE_HW_SHA
#endif // MY_CPU_ARM_OR_ARM64
#if !defined(USE_HW_SHA) && defined(Z7_USE_HW_SHA_STUB)
// #error Stop_Compiling_UNSUPPORTED_SHA
// #include <stdlib.h>
// We can compile this file with another C compiler,
// or we can compile asm version.
// So we can generate real code instead of this stub function.
// #include "Sha512.h"
// #if defined(_MSC_VER)
#pragma message("Sha512 HW-SW stub was used")
// #endif
void Z7_FASTCALL Sha512_UpdateBlocks (UInt64 state[8], const Byte *data, size_t numBlocks);
void Z7_FASTCALL Sha512_UpdateBlocks_HW(UInt64 state[8], const Byte *data, size_t numBlocks);
void Z7_FASTCALL Sha512_UpdateBlocks_HW(UInt64 state[8], const Byte *data, size_t numBlocks)
{
Sha512_UpdateBlocks(state, data, numBlocks);
/*
UNUSED_VAR(state);
UNUSED_VAR(data);
UNUSED_VAR(numBlocks);
exit(1);
return;
*/
}
#endif
#undef K
#undef RND2
#undef MY_rev64_for_LE
#undef NN
#undef NNN
#undef LOAD_128
#undef STORE_128
#undef LOAD_SHUFFLE
#undef SM1
#undef SM2
#undef SM
#undef R2
#undef R4
#undef R16
#undef PREPARE_STATE
#undef USE_HW_SHA
#undef ATTRIB_SHA512
#undef USE_VER_MIN
#undef Z7_USE_HW_SHA_STUB

View file

@ -1,5 +1,5 @@
/* ZstdDec.c -- Zstd Decoder
2024-05-26 : the code was developed by Igor Pavlov, using Zstandard format
2024-06-18 : the code was developed by Igor Pavlov, using Zstandard format
specification and original zstd decoder code as reference code.
original zstd decoder code: Copyright (c) Facebook, Inc. All rights reserved.
This source code is licensed under BSD 3-Clause License.
@ -1308,8 +1308,10 @@ FSE_Decode_SeqTable(CFseRecord * const table,
in->len--;
{
const Byte *ptr = in->ptr;
const Byte sym = ptr[0];
const unsigned sym = ptr[0];
in->ptr = ptr + 1;
if (sym >= numSymbolsMax)
return SZ_ERROR_DATA;
table[0] = (FastInt32)sym
#if defined(Z7_ZSTD_DEC_USE_ML_PLUS3)
+ (numSymbolsMax == NUM_ML_SYMBOLS ? MATCH_LEN_MIN : 0)

View file

@ -220,6 +220,9 @@ endif
all: $(O) $(PROGPATH) $(STATIC_TARGET)
# we need $(O) as order-only-prerequisites:
$(OBJS): | $(O)
$(O):
$(MY_MKDIR) $(O)
@ -299,6 +302,8 @@ $O/ListFileUtils.o: ../../../Common/ListFileUtils.cpp
$(CXX) $(CXXFLAGS) $<
$O/LzFindPrepare.o: ../../../Common/LzFindPrepare.cpp
$(CXX) $(CXXFLAGS) $<
$O/Md5Reg.o: ../../../Common/Md5Reg.cpp
$(CXX) $(CXXFLAGS) $<
$O/MyMap.o: ../../../Common/MyMap.cpp
$(CXX) $(CXXFLAGS) $<
$O/MyString.o: ../../../Common/MyString.cpp
@ -323,6 +328,12 @@ $O/Sha256Prepare.o: ../../../Common/Sha256Prepare.cpp
$(CXX) $(CXXFLAGS) $<
$O/Sha256Reg.o: ../../../Common/Sha256Reg.cpp
$(CXX) $(CXXFLAGS) $<
$O/Sha3Reg.o: ../../../Common/Sha3Reg.cpp
$(CXX) $(CXXFLAGS) $<
$O/Sha512Prepare.o: ../../../Common/Sha512Prepare.cpp
$(CXX) $(CXXFLAGS) $<
$O/Sha512Reg.o: ../../../Common/Sha512Reg.cpp
$(CXX) $(CXXFLAGS) $<
$O/StdInStream.o: ../../../Common/StdInStream.cpp
$(CXX) $(CXXFLAGS) $<
$O/StdOutStream.o: ../../../Common/StdOutStream.cpp
@ -1204,6 +1215,8 @@ $O/Lzma2Enc.o: ../../../../C/Lzma2Enc.c
$(CC) $(CFLAGS) $<
$O/LzmaLib.o: ../../../../C/LzmaLib.c
$(CC) $(CFLAGS) $<
$O/Md5.o: ../../../../C/Md5.c
$(CC) $(CFLAGS) $<
$O/MtCoder.o: ../../../../C/MtCoder.c
$(CC) $(CFLAGS) $<
$O/MtDec.o: ../../../../C/MtDec.c
@ -1226,6 +1239,12 @@ $O/Sha1.o: ../../../../C/Sha1.c
$(CC) $(CFLAGS) $<
$O/Sha256.o: ../../../../C/Sha256.c
$(CC) $(CFLAGS) $<
$O/Sha3.o: ../../../../C/Sha3.c
$(CC) $(CFLAGS) $<
$O/Sha512.o: ../../../../C/Sha512.c
$(CC) $(CFLAGS) $<
$O/Sha512Opt.o: ../../../../C/Sha512Opt.c
$(CC) $(CFLAGS) $<
$O/Sort.o: ../../../../C/Sort.c
$(CC) $(CFLAGS) $<
$O/SwapBytes.o: ../../../../C/SwapBytes.c

View file

@ -219,6 +219,14 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)
}
/*
Filters don't improve the compression ratio for relocatable object files (".o").
But we can get compression ratio gain, if we compress object
files and executables in same solid block.
So we use filters for relocatable object files (".o"):
*/
// #define Z7_7Z_CREATE_ARC_DISABLE_FILTER_FOR_OBJ
/* ---------- ELF ---------- */
#define ELF_SIG 0x464C457F
@ -258,6 +266,12 @@ static int Parse_ELF(const Byte *buf, size_t size, CFilterMode *filterMode)
default: return 0;
}
#ifdef Z7_7Z_CREATE_ARC_DISABLE_FILTER_FOR_OBJ
#define ELF_ET_REL 1
if (Get16(buf + 0x10, be) == ELF_ET_REL)
return 0;
#endif
switch (Get16(buf + 0x12, be))
{
case 3:
@ -318,6 +332,12 @@ static unsigned Parse_MACH(const Byte *buf, size_t size, CFilterMode *filterMode
default: return 0;
}
#ifdef Z7_7Z_CREATE_ARC_DISABLE_FILTER_FOR_OBJ
#define MACH_TYPE_OBJECT 1
if (Get32(buf + 0xC, be) == MACH_TYPE_OBJECT)
return 0;
#endif
switch (Get32(buf + 4, be))
{
case MACH_MACHINE_386:

View file

@ -6,7 +6,6 @@
#include "../../Common/ComTry.h"
#include "../../Windows/PropVariant.h"
#include "../../Windows/PropVariantUtils.h"
#include "../Common/RegisterArc.h"
@ -14,8 +13,7 @@
#include "HandlerCont.h"
// #define Get16(p) GetBe16(p)
#define Get32(p) GetBe32(p)
#define Get32(p) GetBe32a(p)
using namespace NWindows;
@ -41,8 +39,8 @@ static const CUInt32PCharPair k_Flags[] =
{ 5, "WRITABLE" },
{ 6, "OS_PIC_CODE" },
// { 7, "OS_SPECIFIC_2" }, // "Unused"
// { 8, "ChainCompatible" }, // "OS_SPECIFIC_1"
// { 9, "RealDeviceDriver" },
{ 8, "ChainCompatible" }, // "OS_SPECIFIC_1"
{ 9, "RealDeviceDriver" },
// { 10, "CanChainToNext" },
{ 30, "MOUNTED_AT_STARTUP" },
{ 31, "STARTUP" }
@ -74,16 +72,16 @@ struct CItem
bool Is_Valid_and_Allocated() const
{ return (Flags & (DPME_FLAGS_VALID | DPME_FLAGS_ALLOCATED)) != 0; }
bool Parse(const Byte *p, UInt32 &numBlocksInMap)
bool Parse(const UInt32 *p32, UInt32 &numBlocksInMap)
{
numBlocksInMap = Get32(p + 4);
StartBlock = Get32(p + 8);
NumBlocks = Get32(p + 0xc);
Flags = Get32(p + 0x58);
memcpy(Name, p + 0x10, k_Str_Size);
memcpy(Type, p + 0x30, k_Str_Size);
if (GetUi32(p) != 0x4d50) // "PM"
if (GetUi32a(p32) != 0x4d50) // "PM"
return false;
numBlocksInMap = Get32(p32 + 4 / 4);
StartBlock = Get32(p32 + 8 / 4);
NumBlocks = Get32(p32 + 0xc / 4);
Flags = Get32(p32 + 0x58 / 4);
memcpy(Name, p32 + 0x10 / 4, k_Str_Size);
memcpy(Type, p32 + 0x30 / 4, k_Str_Size);
/*
DataStartBlock = Get32(p + 0x50);
NumDataBlocks = Get32(p + 0x54);
@ -96,7 +94,7 @@ struct CItem
if (Get32(p + 0x70) != 0)
return false;
BootChecksum = Get32(p + 0x74);
memcpy(Processor, p + 0x78, 16);
memcpy(Processor, p32 + 0x78 / 4, 16);
*/
return true;
}
@ -109,9 +107,9 @@ Z7_class_CHandler_final: public CHandlerCont
CRecordVector<CItem> _items;
unsigned _blockSizeLog;
UInt32 _numBlocks;
UInt64 _phySize;
bool _isArc;
// UInt32 _numBlocks;
UInt64 _phySize;
UInt64 BlocksToBytes(UInt32 i) const { return (UInt64)i << _blockSizeLog; }
@ -132,11 +130,11 @@ API_FUNC_static_IsArc IsArc_Apm(const Byte *p, size_t size)
{
if (size < kSectorSize)
return k_IsArc_Res_NEED_MORE;
if (GetUi64(p + 8) != 0)
if (GetUi32(p + 12) != 0)
return k_IsArc_Res_NO;
UInt32 v = GetUi32(p); // we read as little-endian
v ^= (kSig0 | (unsigned)kSig1 << 8);
if ((v & ~((UInt32)0xf << 17)))
v ^= kSig0 | (unsigned)kSig1 << 8;
if (v & ~((UInt32)0xf << 17))
return k_IsArc_Res_NO;
if ((0x116u >> (v >> 17)) & 1)
return k_IsArc_Res_YES;
@ -149,55 +147,103 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
COM_TRY_BEGIN
Close();
Byte buf[kSectorSize];
unsigned numSectors_in_Cluster;
UInt32 buf32[kSectorSize / 4];
unsigned numPadSectors, blockSizeLog_from_Header;
{
RINOK(ReadStream_FALSE(stream, buf, kSectorSize))
if (GetUi64(buf + 8) != 0)
// Driver Descriptor Map (DDM)
RINOK(ReadStream_FALSE(stream, buf32, kSectorSize))
// 8: UInt16 sbDevType : =0 (usually), =1 in Apple Mac OS X 10.3.0 iso
// 10: UInt16 sbDevId : =0 (usually), =1 in Apple Mac OS X 10.3.0 iso
// 12: UInt32 sbData : =0
if (buf32[3] != 0)
return S_FALSE;
UInt32 v = GetUi32(buf); // we read as little-endian
v ^= (kSig0 | (unsigned)kSig1 << 8);
if ((v & ~((UInt32)0xf << 17)))
UInt32 v = GetUi32a(buf32); // we read as little-endian
v ^= kSig0 | (unsigned)kSig1 << 8;
if (v & ~((UInt32)0xf << 17))
return S_FALSE;
v >>= 16;
if (v == 0)
return S_FALSE;
if (v & (v - 1))
return S_FALSE;
const unsigned a = (0x30210u >> v) & 3;
// a = 0; // for debug
numSectors_in_Cluster = 1u << a;
_blockSizeLog = 9 + a;
// v == { 16,8,4,2 } : block size (x256 bytes)
const unsigned a =
#if 1
(0x30210u >> v) & 3;
#else
0; // for debug : hardcoded switch to 512-bytes mode
#endif
numPadSectors = (1u << a) - 1;
_blockSizeLog = blockSizeLog_from_Header = 9 + a;
}
UInt32 numBlocks = Get32(buf + 4);
_numBlocks = numBlocks;
/*
some APMs (that are ".iso" macOS installation files) contain
(blockSizeLog == 11) in DDM header,
and contain 2 overlapping maps:
1) map for 512-bytes-step
2) map for 2048-bytes-step
512-bytes-step map is correct.
2048-bytes-step map can be incorrect in some cases.
macos 8 / OSX DP2 iso:
There is shared "hfs" item in both maps.
And correct (offset/size) values for "hfs" partition
can be calculated only in 512-bytes mode (ignoring blockSizeLog == 11).
But some records (Macintosh.Apple_Driver*_)
can be correct on both modes: 512-bytes mode / 2048-bytes-step.
macos 921 ppc / Apple Mac OS X 10.3.0 iso:
Both maps are correct.
If we use 512-bytes-step, each 4th item is (Apple_Void) with zero size.
And these zero size (Apple_Void) items will be first items in 2048-bytes-step map.
*/
// we define Z7_APM_SWITCH_TO_512_BYTES, because
// we want to support old MACOS APMs that contain correct value only
// for 512-bytes-step mode
#define Z7_APM_SWITCH_TO_512_BYTES
const UInt32 numBlocks_from_Header = Get32(buf32 + 1);
UInt32 numBlocks = 0;
{
for (unsigned k = numSectors_in_Cluster; --k != 0;)
for (unsigned k = 0; k < numPadSectors; k++)
{
RINOK(ReadStream_FALSE(stream, buf, kSectorSize))
RINOK(ReadStream_FALSE(stream, buf32, kSectorSize))
#ifdef Z7_APM_SWITCH_TO_512_BYTES
if (k == 0)
{
if (GetUi32a(buf32) == 0x4d50 // "PM"
// && (Get32(buf32 + 0x58 / 4) & 1) // Flags::VALID
// some old APMs don't use VALID flag for Apple_partition_map item
&& Get32(buf32 + 8 / 4) == 1) // StartBlock
{
// we switch the mode to 512-bytes-step map reading:
numPadSectors = 0;
_blockSizeLog = 9;
break;
}
}
#endif
}
}
UInt32 numBlocksInMap = 0;
for (unsigned i = 0;;)
{
RINOK(ReadStream_FALSE(stream, buf, kSectorSize))
#ifdef Z7_APM_SWITCH_TO_512_BYTES
if (i != 0 || _blockSizeLog == blockSizeLog_from_Header)
#endif
{
RINOK(ReadStream_FALSE(stream, buf32, kSectorSize))
}
CItem item;
UInt32 numBlocksInMap2 = 0;
if (!item.Parse(buf, numBlocksInMap2))
UInt32 numBlocksInMap = 0;
if (!item.Parse(buf32, numBlocksInMap))
return S_FALSE;
if (i == 0)
{
numBlocksInMap = numBlocksInMap2;
if (numBlocksInMap > (1 << 8) || numBlocksInMap == 0)
return S_FALSE;
}
else if (numBlocksInMap2 != numBlocksInMap)
// v24.09: we don't check that all entries have same (numBlocksInMap) values,
// because some APMs have different (numBlocksInMap) values, if (Apple_Void) is used.
if (numBlocksInMap > (1 << 8) || numBlocksInMap <= i)
return S_FALSE;
const UInt32 finish = item.StartBlock + item.NumBlocks;
@ -207,15 +253,19 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
numBlocks = finish;
_items.Add(item);
for (unsigned k = numSectors_in_Cluster; --k != 0;)
if (numPadSectors != 0)
{
RINOK(ReadStream_FALSE(stream, buf, kSectorSize))
RINOK(stream->Seek(numPadSectors << 9, STREAM_SEEK_CUR, NULL))
}
if (++i == numBlocksInMap)
break;
}
_phySize = BlocksToBytes(numBlocks);
// _numBlocks = numBlocks;
const UInt64 physSize = (UInt64)numBlocks_from_Header << blockSizeLog_from_Header;
if (_phySize < physSize)
_phySize = physSize;
_isArc = true;
_stream = stream;
@ -240,22 +290,21 @@ static const Byte kProps[] =
kpidSize,
kpidOffset,
kpidCharacts
// , kpidCpu
};
static const Byte kArcProps[] =
{
kpidClusterSize,
kpidNumBlocks
kpidClusterSize
// , kpidNumBlocks
};
IMP_IInArchive_Props
IMP_IInArchive_ArcProps
static AString GetString(const char *s)
static void GetString(AString &dest, const char *src)
{
AString res;
res.SetFrom_CalcLen(s, k_Str_Size);
return res;
dest.SetFrom_CalcLen(src, k_Str_Size);
}
Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
@ -272,7 +321,8 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
const CItem &item = _items[i];
if (!item.Is_Valid_and_Allocated())
continue;
AString s (GetString(item.Type));
AString s;
GetString(s, item.Type);
if (NDmg::Is_Apple_FS_Or_Unknown(s))
{
if (mainIndex != -1)
@ -289,7 +339,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
}
case kpidClusterSize: prop = (UInt32)1 << _blockSizeLog; break;
case kpidPhySize: prop = _phySize; break;
case kpidNumBlocks: prop = _numBlocks; break;
// case kpidNumBlocks: prop = _numBlocks; break;
case kpidErrorFlags:
{
@ -319,10 +369,12 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
case kpidPath:
{
AString s (GetString(item.Name));
AString s;
GetString(s, item.Name);
if (s.IsEmpty())
s.Add_UInt32(index);
AString type (GetString(item.Type));
AString type;
GetString(type, item.Type);
{
const char *ext = NDmg::Find_Apple_FS_Ext(type);
if (ext)
@ -336,6 +388,16 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop = s;
break;
}
/*
case kpidCpu:
{
AString s;
s.SetFrom_CalcLen(item.Processor, sizeof(item.Processor));
if (!s.IsEmpty())
prop = s;
break;
}
*/
case kpidSize:
case kpidPackSize:
prop = BlocksToBytes(item.NumBlocks);

View file

@ -22,7 +22,7 @@ protected:
_numThreads_WasForced = false;
#endif
UInt64 memAvail = (UInt64)(sizeof(size_t)) << 28;
size_t memAvail = (size_t)sizeof(size_t) << 28;
_memAvail = memAvail;
_memUsage_Compress = memAvail;
_memUsage_Decompress = memAvail;
@ -55,7 +55,7 @@ public:
bool _memUsage_WasSet;
UInt64 _memUsage_Compress;
UInt64 _memUsage_Decompress;
UInt64 _memAvail;
size_t _memAvail;
bool SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres);

View file

@ -17,11 +17,13 @@
#include "../Compress/CopyCoder.h"
// #define Z7_ELF_SHOW_DETAILS
using namespace NWindows;
static UInt16 Get16(const Byte *p, bool be) { if (be) return GetBe16(p); return GetUi16(p); }
static UInt32 Get32(const Byte *p, bool be) { if (be) return GetBe32(p); return GetUi32(p); }
static UInt64 Get64(const Byte *p, bool be) { if (be) return GetBe64(p); return GetUi64(p); }
static UInt16 Get16(const Byte *p, bool be) { if (be) return GetBe16a(p); return GetUi16a(p); }
static UInt32 Get32(const Byte *p, bool be) { if (be) return GetBe32a(p); return GetUi32a(p); }
static UInt64 Get64(const Byte *p, bool be) { if (be) return GetBe64a(p); return GetUi64a(p); }
#define G16(offs, v) v = Get16(p + (offs), be)
#define G32(offs, v) v = Get32(p + (offs), be)
@ -31,14 +33,51 @@ namespace NArchive {
namespace NElf {
/*
ELF Structure for most files (real order can be different):
Header
Program (segment) header table (used at runtime)
Segment1 (Section ... Section)
Segment2
...
SegmentN
Section header table (the data for linking and relocation)
ELF Structure example:
{
Header
Program header table (is used at runtime) (list of segment metadata records)
{
Segment (Read)
Segment : PT_PHDR : header table itself
Segment : PT_INTERP
Segment : PT_NOTE
.rela.dyn (RELA, ALLOC)
Segment (Execute/Read)
.text section (PROGBITS, SHF_ALLOC | SHF_EXECINSTR)
Segment (Read)
.rodata (PROGBITS, SHF_ALLOC | SHF_WRITE)
Segment : PT_GNU_EH_FRAME
.eh_frame_hdr
.eh_frame
.gcc_except_table
...
Segment (Write/Read) (VaSize > Size)
Segment (Read) : PT_GNU_RELRO
Segment (Write/Read)
.data
.bss (Size == 0) (VSize != 0)
}
.comment (VA == 0)
.shstrtab (VA == 0)
Section header table (the data for linking and relocation)
}
Last top level segment contains .bss section that requires additional VA space.
So (VaSize > Size) for that segment.
Segments can be unsorted (by offset) in table.
Top level segments has Type=PT_LOAD : "Loadable segment".
Top level segments usually are aligned for page size (4 KB).
Another segments (non PT_LOAD segments) are inside PT_LOAD segments.
(VA-offset == 0) is possible for some sections and segments at the beginning of file.
(VA-offset == 4KB*N) for most sections and segments where (Size != 0),
(VA-offset != 4KB*N) for .bss section (last section), because (Size == 0),
and that section is not mapped from image file.
Some files contain additional "virtual" 4 KB page in VA space after
end of data of top level segments (PT_LOAD) before new top level segments.
So (VA-offset) value can increase by 4 KB step.
*/
#define ELF_CLASS_32 1
@ -47,14 +86,14 @@ namespace NElf {
#define ELF_DATA_2LSB 1
#define ELF_DATA_2MSB 2
static const UInt32 kHeaderSize32 = 0x34;
static const UInt32 kHeaderSize64 = 0x40;
static const unsigned kHeaderSize32 = 0x34;
static const unsigned kHeaderSize64 = 0x40;
static const UInt32 kSegmentSize32 = 0x20;
static const UInt32 kSegmentSize64 = 0x38;
static const unsigned kSegmentSize32 = 0x20;
static const unsigned kSegmentSize64 = 0x38;
static const UInt32 kSectionSize32 = 0x28;
static const UInt32 kSectionSize64 = 0x40;
static const unsigned kSectionSize32 = 0x28;
static const unsigned kSectionSize64 = 0x40;
struct CHeader
{
@ -78,9 +117,9 @@ struct CHeader
UInt16 NumSections;
UInt16 NamesSectIndex;
bool Parse(const Byte *buf);
bool Parse(const Byte *p);
UInt64 GetHeadersSize() const { return (UInt64)HeaderSize +
UInt32 GetHeadersSize() const { return (UInt32)HeaderSize +
(UInt32)NumSegments * SegmentEntrySize +
(UInt32)NumSections * SectionEntrySize; }
};
@ -104,7 +143,7 @@ bool CHeader::Parse(const Byte *p)
if (p[6] != 1) // Version
return false;
Os = p[7];
AbiVer = p[8];
// AbiVer = p[8];
for (int i = 9; i < 16; i++)
if (p[i] != 0)
return false;
@ -117,16 +156,21 @@ bool CHeader::Parse(const Byte *p)
if (Mode64)
{
// G64(0x18, EntryVa);
G64(0x20, ProgOffset);
G64(0x20, ProgOffset); // == kHeaderSize64 == 0x40 usually
G64(0x28, SectOffset);
p += 0x30;
// we expect that fields are aligned
if (ProgOffset & 7) return false;
if (SectOffset & 7) return false;
}
else
{
// G32(0x18, EntryVa);
G32(0x1C, ProgOffset);
G32(0x1C, ProgOffset); // == kHeaderSize32 == 0x34 usually
G32(0x20, SectOffset);
p += 0x24;
if (ProgOffset & 3) return false;
if (SectOffset & 3) return false;
}
G32(0, Flags);
@ -140,21 +184,20 @@ bool CHeader::Parse(const Byte *p)
G16(12, NumSections);
G16(14, NamesSectIndex);
if (ProgOffset < HeaderSize && (ProgOffset != 0 || NumSegments != 0)) return false;
if (SectOffset < HeaderSize && (SectOffset != 0 || NumSections != 0)) return false;
if (ProgOffset < HeaderSize && (ProgOffset || NumSegments)) return false;
if (SectOffset < HeaderSize && (SectOffset || NumSections)) return false;
if (SegmentEntrySize == 0) { if (NumSegments != 0) return false; }
if (SegmentEntrySize == 0) { if (NumSegments) return false; }
else if (SegmentEntrySize != (Mode64 ? kSegmentSize64 : kSegmentSize32)) return false;
if (SectionEntrySize == 0) { if (NumSections != 0) return false; }
if (SectionEntrySize == 0) { if (NumSections) return false; }
else if (SectionEntrySize != (Mode64 ? kSectionSize64 : kSectionSize32)) return false;
return true;
}
// The program header table itself.
#define PT_PHDR 6
#define PT_PHDR 6 // The program header table itself.
#define PT_GNU_STACK 0x6474e551
static const CUInt32PCharPair g_SegnmentTypes[] =
@ -186,16 +229,18 @@ struct CSegment
UInt32 Flags;
UInt64 Offset;
UInt64 Va;
// UInt64 Pa;
UInt64 Size;
UInt64 VSize;
UInt64 Align;
UInt64 Size; // size in file
UInt64 VSize; // size in memory
#ifdef Z7_ELF_SHOW_DETAILS
UInt64 Pa; // usually == Va, or == 0
UInt64 Align; // if (Align != 0), condition must be met:
// (VSize % Align == Offset % Alig)
#endif
void UpdateTotalSize(UInt64 &totalSize)
{
UInt64 t = Offset + Size;
const UInt64 t = Offset + Size;
if (totalSize < t)
totalSize = t;
totalSize = t;
}
void Parse(const Byte *p, bool mode64, bool be);
};
@ -208,20 +253,24 @@ void CSegment::Parse(const Byte *p, bool mode64, bool be)
G32(4, Flags);
G64(8, Offset);
G64(0x10, Va);
// G64(0x18, Pa);
G64(0x20, Size);
G64(0x28, VSize);
#ifdef Z7_ELF_SHOW_DETAILS
G64(0x18, Pa);
G64(0x30, Align);
#endif
}
else
{
G32(4, Offset);
G32(8, Va);
// G32(0x0C, Pa);
G32(0x10, Size);
G32(0x14, VSize);
G32(0x18, Flags);
#ifdef Z7_ELF_SHOW_DETAILS
G32(0x0C, Pa);
G32(0x1C, Align);
#endif
}
}
@ -290,6 +339,8 @@ static const CUInt32PCharPair g_SectTypes[] =
{ 0x70000005, "ARM_OVERLAYSECTION" }
};
// SHF_ flags
static const CUInt32PCharPair g_SectionFlags[] =
{
{ 0, "WRITE" },
@ -303,7 +354,7 @@ static const CUInt32PCharPair g_SectionFlags[] =
{ 8, "OS_NONCONFORMING" },
{ 9, "GROUP" },
{ 10, "TLS" },
{ 11, "CP_SECTION" },
{ 11, "COMPRESSED" },
{ 12, "DP_SECTION" },
{ 13, "XCORE_SHF_CP_SECTION" },
{ 28, "64_LARGE" },
@ -326,9 +377,9 @@ struct CSection
void UpdateTotalSize(UInt64 &totalSize)
{
UInt64 t = Offset + GetSize();
const UInt64 t = Offset + GetSize();
if (totalSize < t)
totalSize = t;
totalSize = t;
}
bool Parse(const Byte *p, bool mode64, bool be);
};
@ -412,7 +463,7 @@ static const char * const g_Machines[] =
, "TRW RH-32"
, "Motorola RCE"
, "ARM"
, "Alpha"
, "Alpha-STD"
, "Hitachi SH"
, "SPARC-V9"
, "Siemens Tricore"
@ -577,8 +628,9 @@ static const char * const g_Machines[] =
static const CUInt32PCharPair g_MachinePairs[] =
{
{ 243, "RISC-V" },
{ 47787, "Xilinx MicroBlaze" }
// { 0x9026, "Alpha" }
{ 258, "LoongArch" },
{ 0x9026, "Alpha" }, // EM_ALPHA_EXP, obsolete, (used by NetBSD/alpha) (written in the absence of an ABI)
{ 0xbaab, "Xilinx MicroBlaze" }
};
static const CUInt32PCharPair g_OS[] =
@ -600,6 +652,8 @@ static const CUInt32PCharPair g_OS[] =
{ 14, "HP NSK" },
{ 15, "AROS" },
{ 16, "FenixOS" },
{ 17, "CloudABI" },
{ 18, "OpenVOS" },
{ 64, "Bare-metal TMS320C6000" },
{ 65, "Linux TMS320C6000" },
{ 97, "ARM" },
@ -693,23 +747,27 @@ public:
void CHandler::GetSectionName(UInt32 index, NCOM::CPropVariant &prop, bool showNULL) const
{
if (index >= _sections.Size())
return;
const CSection &section = _sections[index];
const UInt32 offset = section.Name;
if (index == SHN_UNDEF /* && section.Type == SHT_NULL && offset == 0 */)
prop = index; // it's possible for some file, but maybe it's ERROR case
else
{
if (showNULL)
prop = "NULL";
return;
}
const Byte *p = _namesData;
size_t size = _namesData.Size();
for (size_t i = offset; i < size; i++)
if (p[i] == 0)
const CSection &section = _sections[index];
const UInt32 offset = section.Name;
if (index == SHN_UNDEF /* && section.Type == SHT_NULL && offset == 0 */)
{
prop = (const char *)(p + offset);
if (showNULL)
prop = "NULL";
return;
}
const Byte *p = _namesData;
const size_t size = _namesData.Size();
for (size_t i = offset; i < size; i++)
if (p[i] == 0)
{
prop = (const char *)(p + offset);
return;
}
prop = "ERROR";
}
}
static const Byte kArcProps[] =
@ -726,7 +784,14 @@ static const Byte kArcProps[] =
enum
{
kpidLinkSection = kpidUserDefined,
kpidInfoSection
kpidInfoSection,
kpidEntrySize
#ifdef Z7_ELF_SHOW_DETAILS
// , kpidAlign
, kpidPa
, kpidDelta
, kpidOffsetEnd
#endif
};
static const CStatProp kProps[] =
@ -738,6 +803,14 @@ static const CStatProp kProps[] =
{ NULL, kpidVa, VT_UI8 },
{ NULL, kpidType, VT_BSTR },
{ NULL, kpidCharacts, VT_BSTR }
#ifdef Z7_ELF_SHOW_DETAILS
// , { "Align", kpidAlign, VT_UI8 }
, { NULL, kpidClusterSize, VT_UI8 }
, { "PA", kpidPa, VT_UI8 }
, { "End offset", kpidOffsetEnd, VT_UI8 }
, { "Delta (VA-Offset)", kpidDelta, VT_UI8 }
#endif
, { "Entry Size", kpidEntrySize, VT_UI8}
, { "Link Section", kpidLinkSection, VT_BSTR}
, { "Info Section", kpidInfoSection, VT_BSTR}
};
@ -769,7 +842,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
if (s.IsEmpty())
s = TypePairToString(g_MachinePairs, Z7_ARRAY_SIZE(g_MachinePairs), _header.Machine);
UInt32 flags = _header.Flags;
if (flags != 0)
if (flags)
{
s.Add_Space();
if (_header.Machine == k_Machine_ARM)
@ -781,18 +854,16 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
else if (_header.Machine == k_Machine_MIPS)
{
const UInt32 ver = flags >> 28;
s += "v";
s.Add_Char('v');
s.Add_UInt32(ver);
flags &= (((UInt32)1 << 28) - 1);
UInt32 abi = (flags >> 12) & 7;
if (abi != 0)
flags &= ((UInt32)1 << 28) - 1;
const UInt32 abi = (flags >> 12) & 7;
if (abi)
{
s += " ABI:";
s.Add_UInt32(abi);
}
flags &= ~((UInt32)7 << 12);
s.Add_Space();
s += FlagsToString(g_MIPS_Flags, Z7_ARRAY_SIZE(g_MIPS_Flags), flags);
}
@ -813,6 +884,31 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
flags &= ~(UInt32)6;
s += FlagsToString(g_RISCV_Flags, Z7_ARRAY_SIZE(g_RISCV_Flags), flags);
}
#if 0
#define k_Machine_LOONGARCH 258
else if (_header.Machine == k_Machine_LOONGARCH)
{
s += "ABI:";
s.Add_UInt32((flags >> 6) & 3);
s.Add_Dot();
s.Add_UInt32((flags >> 3) & 7);
s.Add_Dot();
#if 1
s.Add_UInt32(flags & 7);
#else
static const char k_LoongArch_Float_Type[8] = { '0', 's', 'f', 'd', '4' ,'5', '6', '7' };
s.Add_Char(k_LoongArch_Float_Type[flags & 7]);
#endif
flags &= ~(UInt32)0xff;
if (flags)
{
s.Add_Colon();
char sz[16];
ConvertUInt32ToHex(flags, sz);
s += sz;
}
}
#endif
else
{
char sz[16];
@ -827,13 +923,39 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
case kpidHostOS: PAIR_TO_PROP(g_OS, _header.Os, prop); break;
case kpidCharacts: TYPE_TO_PROP(g_Types, _header.Type, prop); break;
case kpidComment:
{
AString s;
if (_stackFlags_Defined)
{
AString s ("STACK: ");
s += "STACK: ";
s += FlagsToString(g_SegmentFlags, Z7_ARRAY_SIZE(g_SegmentFlags), _stackFlags);
prop = s;
s.Add_LF();
/*
if (_header.EntryVa)
{
s += "Entry point: 0x";
char temp[16 + 4];
ConvertUInt64ToHex(_header.EntryVa, temp);
s += temp;
s.Add_LF();
}
*/
}
if (_header.NumSegments)
{
s += "Segments: ";
s.Add_UInt32(_header.NumSegments);
s.Add_LF();
}
if (_header.NumSections)
{
s += "Sections: ";
s.Add_UInt32(_header.NumSections);
s.Add_LF();
}
prop = s;
break;
}
case kpidExtension:
{
const char *s = NULL;
@ -878,12 +1000,17 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
}
case kpidOffset: prop = item.Offset; break;
case kpidVa: prop = item.Va; break;
#ifdef Z7_ELF_SHOW_DETAILS
case kpidDelta: if (item.Va) { prop = item.Va - item.Offset; } break;
case kpidOffsetEnd: prop = item.Offset + item.Size; break;
case kpidPa: prop = item.Pa; break;
case kpidClusterSize: prop = item.Align; break;
#endif
case kpidSize:
case kpidPackSize: prop = (UInt64)item.Size; break;
case kpidVirtualSize: prop = (UInt64)item.VSize; break;
case kpidType: PAIR_TO_PROP(g_SegnmentTypes, item.Type, prop); break;
case kpidCharacts: FLAGS_TO_PROP(g_SegmentFlags, item.Flags, prop); break;
}
}
else
@ -895,13 +1022,19 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidPath: GetSectionName(index, prop, true); break;
case kpidOffset: prop = item.Offset; break;
case kpidVa: prop = item.Va; break;
#ifdef Z7_ELF_SHOW_DETAILS
case kpidDelta: if (item.Va) { prop = item.Va - item.Offset; } break;
case kpidOffsetEnd: prop = item.Offset + item.GetSize(); break;
#endif
case kpidSize:
case kpidPackSize: prop = (UInt64)(item.Type == SHT_NOBITS ? 0 : item.VSize); break;
case kpidVirtualSize: prop = item.GetSize(); break;
case kpidType: PAIR_TO_PROP(g_SectTypes, item.Type, prop); break;
case kpidCharacts: FLAGS_TO_PROP(g_SectionFlags, (UInt32)item.Flags, prop); break;
// case kpidAlign: prop = item.Align; break;
case kpidLinkSection: GetSectionName(item.Link, prop, false); break;
case kpidInfoSection: GetSectionName(item.Info, prop, false); break;
case kpidEntrySize: prop = (UInt64)item.EntSize; break;
}
}
prop.Detach(value);
@ -911,42 +1044,46 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
HRESULT CHandler::Open2(IInStream *stream)
{
const UInt32 kStartSize = kHeaderSize64;
Byte h[kStartSize];
RINOK(ReadStream_FALSE(stream, h, kStartSize))
if (h[0] != 0x7F || h[1] != 'E' || h[2] != 'L' || h[3] != 'F')
return S_FALSE;
if (!_header.Parse(h))
return S_FALSE;
{
const UInt32 kStartSize = kHeaderSize64;
UInt64 h64[kStartSize / 8];
RINOK(ReadStream_FALSE(stream, h64, kStartSize))
const Byte *h = (const Byte *)(const void *)h64;
if (GetUi32a(h) != 0x464c457f)
return S_FALSE;
if (!_header.Parse(h))
return S_FALSE;
}
_totalSize = _header.HeaderSize;
bool addSegments = false;
bool addSections = false;
if (_header.NumSections > 1)
// first section usually is NULL (with zero offsets and zero sizes).
if (_header.NumSegments == 0 || _header.NumSections > 1)
addSections = true;
else
addSegments = true;
#ifdef Z7_ELF_SHOW_DETAILS
addSections = true;
addSegments = true;
#endif
if (_header.NumSegments != 0)
if (_header.NumSegments)
{
if (_header.ProgOffset > (UInt64)1 << 60) return S_FALSE;
RINOK(InStream_SeekSet(stream, _header.ProgOffset))
const size_t size = (size_t)_header.SegmentEntrySize * _header.NumSegments;
CByteArr buf(size);
RINOK(ReadStream_FALSE(stream, buf, size))
const UInt64 total = _header.ProgOffset + size;
if (_totalSize < total)
_totalSize = total;
const Byte *p = buf;
{
const UInt64 total = _header.ProgOffset + size;
if (_totalSize < total)
_totalSize = total;
}
if (addSegments)
_segments.ClearAndReserve(_header.NumSegments);
const Byte *p = buf;
for (unsigned i = 0; i < _header.NumSegments; i++, p += _header.SegmentEntrySize)
{
CSegment seg;
@ -957,29 +1094,29 @@ HRESULT CHandler::Open2(IInStream *stream)
_stackFlags = seg.Flags;
_stackFlags_Defined = true;
}
if (addSegments && seg.Type != PT_PHDR)
if (addSegments
// we don't show program header table segment
&& seg.Type != PT_PHDR
)
_segments.AddInReserved(seg);
}
}
if (_header.NumSections != 0)
if (_header.NumSections)
{
if (_header.SectOffset > (UInt64)1 << 60) return S_FALSE;
RINOK(InStream_SeekSet(stream, _header.SectOffset))
size_t size = (size_t)_header.SectionEntrySize * _header.NumSections;
const size_t size = (size_t)_header.SectionEntrySize * _header.NumSections;
CByteArr buf(size);
RINOK(ReadStream_FALSE(stream, buf, size))
UInt64 total = _header.SectOffset + size;
if (_totalSize < total)
_totalSize = total;
const Byte *p = buf;
{
const UInt64 total = _header.SectOffset + size;
if (_totalSize < total)
_totalSize = total;
}
if (addSections)
_sections.ClearAndReserve(_header.NumSections);
const Byte *p = buf;
for (unsigned i = 0; i < _header.NumSections; i++, p += _header.SectionEntrySize)
{
CSection sect;
@ -1000,18 +1137,17 @@ HRESULT CHandler::Open2(IInStream *stream)
{
const CSection &sect = _sections[_header.NamesSectIndex];
const UInt64 size = sect.GetSize();
if (size != 0
&& size < ((UInt64)1 << 31)
&& (Int64)sect.Offset >= 0)
if (size && size < ((UInt64)1 << 31)
&& (Int64)sect.Offset >= 0)
{
_namesData.Alloc((size_t)size);
RINOK(InStream_SeekSet(stream, sect.Offset))
RINOK(ReadStream_FALSE(stream, _namesData, (size_t)size))
}
}
/*
// we will not delete NULL sections, since we have links to section via indexes
// we cannot delete "NULL" sections,
// because we have links to sections array via indexes
for (int i = _sections.Size() - 1; i >= 0; i--)
if (_sections[i].Type == SHT_NULL)
_items.Delete(i);
@ -1080,7 +1216,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
RINOK(extractCallback->SetTotal(totalSize))
UInt64 currentTotalSize = 0;
totalSize = 0;
UInt64 currentItemSize;
CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
@ -1089,9 +1225,9 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
inStream->SetStream(_inStream);
for (i = 0;; i++, currentTotalSize += currentItemSize)
for (i = 0;; i++, totalSize += currentItemSize)
{
lps->InSize = lps->OutSize = currentTotalSize;
lps->InSize = lps->OutSize = totalSize;
RINOK(lps->SetCur())
if (i >= numItems)
break;

View file

@ -111,6 +111,12 @@ static const CPartType kPartTypes[] =
{ 0x0FC63DAF, NULL, "Linux Data" },
{ 0x0657FD6D, NULL, "Linux Swap" },
{ 0x44479540, NULL, "Linux root (x86)" },
{ 0x4F68BCE3, NULL, "Linux root (x86-64)" },
{ 0x69DAD710, NULL, "Linux root (ARM)" },
{ 0xB921B045, NULL, "Linux root (ARM64)" },
{ 0x993D8D3D, NULL, "Linux root (IA-64)" },
{ 0x83BD6B9D, NULL, "FreeBSD Boot" },
{ 0x516E7CB4, NULL, "FreeBSD Data" },

View file

@ -25,6 +25,9 @@
#define Get32(p) GetBe32(p)
#define Get64(p) GetBe64(p)
#define Get16a(p) GetBe16a(p)
#define Get32a(p) GetBe32a(p)
namespace NArchive {
namespace NHfs {
@ -104,23 +107,21 @@ UInt32 CFork::Calc_NumBlocks_from_Extents() const
{
UInt32 num = 0;
FOR_VECTOR (i, Extents)
{
num += Extents[i].NumBlocks;
}
return num;
}
bool CFork::Check_NumBlocks() const
{
UInt32 num = 0;
UInt32 num = NumBlocks;
FOR_VECTOR (i, Extents)
{
UInt32 next = num + Extents[i].NumBlocks;
if (next < num)
const UInt32 cur = Extents[i].NumBlocks;
if (num < cur)
return false;
num = next;
num -= cur;
}
return num == NumBlocks;
return num == 0;
}
struct CIdIndexPair
@ -175,7 +176,7 @@ static int Find_in_IdExtents(const CObjectVector<CIdExtents> &items, UInt32 id)
bool CFork::Upgrade(const CObjectVector<CIdExtents> &items, UInt32 id)
{
int index = Find_in_IdExtents(items, id);
const int index = Find_in_IdExtents(items, id);
if (index < 0)
return true;
const CIdExtents &item = items[index];
@ -188,8 +189,13 @@ bool CFork::Upgrade(const CObjectVector<CIdExtents> &items, UInt32 id)
struct CVolHeader
{
Byte Header[2];
UInt16 Version;
unsigned BlockSizeLog;
UInt32 NumFiles;
UInt32 NumFolders;
UInt32 NumBlocks;
UInt32 NumFreeBlocks;
bool Is_Hsfx_ver5;
// UInt32 Attr;
// UInt32 LastMountedVersion;
// UInt32 JournalInfoBlock;
@ -199,19 +205,13 @@ struct CVolHeader
// UInt32 BackupTime;
// UInt32 CheckedTime;
UInt32 NumFiles;
UInt32 NumFolders;
unsigned BlockSizeLog;
UInt32 NumBlocks;
UInt32 NumFreeBlocks;
// UInt32 WriteCount;
// UInt32 FinderInfo[8];
// UInt64 VolID;
UInt64 GetPhySize() const { return (UInt64)NumBlocks << BlockSizeLog; }
UInt64 GetFreeSize() const { return (UInt64)NumFreeBlocks << BlockSizeLog; }
bool IsHfsX() const { return Version > 4; }
bool IsHfsX() const { return Is_Hsfx_ver5; }
};
inline void HfsTimeToFileTime(UInt32 hfsTime, FILETIME &ft)
@ -463,18 +463,18 @@ public:
bool UnsupportedFeature;
bool ThereAreAltStreams;
// bool CaseSensetive;
UInt32 MethodsMask;
UString ResFileName;
UInt64 SpecOffset;
UInt64 PhySize;
// UInt64 PhySize;
UInt64 PhySize2;
UInt64 ArcFileSize;
UInt32 MethodsMask;
void Clear()
{
SpecOffset = 0;
PhySize = 0;
// PhySize = 0;
PhySize2 = 0;
ArcFileSize = 0;
MethodsMask = 0;
@ -596,7 +596,7 @@ HRESULT CDatabase::ReadFile(const CFork &fork, CByteBuffer &buf, IInStream *inSt
{
if (fork.NumBlocks >= Header.NumBlocks)
return S_FALSE;
if ((ArcFileSize >> Header.BlockSizeLog) + 1 < fork.NumBlocks)
if (((ArcFileSize - SpecOffset) >> Header.BlockSizeLog) + 1 < fork.NumBlocks)
return S_FALSE;
const size_t totalSize = (size_t)fork.NumBlocks << Header.BlockSizeLog;
@ -1328,28 +1328,26 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents
return S_OK;
}
static const unsigned kHeaderPadSize = (1 << 10);
static const unsigned kHeaderPadSize = 1 << 10;
static const unsigned kMainHeaderSize = 512;
static const unsigned kHfsHeaderSize = kHeaderPadSize + kMainHeaderSize;
static const unsigned k_Signature_LE16_HFS_BD = 'B' + ((unsigned)'D' << 8);
static const unsigned k_Signature_LE16_HPLUS = 'H' + ((unsigned)'+' << 8);
static const UInt32 k_Signature_LE32_HFSP_VER4 = 'H' + ((UInt32)'+' << 8) + ((UInt32)4 << 24);
static const UInt32 k_Signature_LE32_HFSX_VER5 = 'H' + ((UInt32)'X' << 8) + ((UInt32)5 << 24);
API_FUNC_static_IsArc IsArc_HFS(const Byte *p, size_t size)
{
if (size < kHfsHeaderSize)
return k_IsArc_Res_NEED_MORE;
p += kHeaderPadSize;
if (p[0] == 'B' && p[1] == 'D')
{
if (p[0x7C] != 'H' || p[0x7C + 1] != '+')
return k_IsArc_Res_NO;
}
else
{
if (p[0] != 'H' || (p[1] != '+' && p[1] != 'X'))
return k_IsArc_Res_NO;
UInt32 version = Get16(p + 2);
if (version < 4 || version > 5)
return k_IsArc_Res_NO;
}
const UInt32 sig = GetUi32(p);
if (sig != k_Signature_LE32_HFSP_VER4)
if (sig != k_Signature_LE32_HFSX_VER5)
if ((UInt16)sig != k_Signature_LE16_HFS_BD
|| GetUi16(p + 0x7c) != k_Signature_LE16_HPLUS)
return k_IsArc_Res_NO;
return k_IsArc_Res_YES;
}
}
@ -1357,30 +1355,42 @@ API_FUNC_static_IsArc IsArc_HFS(const Byte *p, size_t size)
HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress)
{
Clear();
Byte buf[kHfsHeaderSize];
RINOK(ReadStream_FALSE(inStream, buf, kHfsHeaderSize))
{
for (unsigned i = 0; i < kHeaderPadSize; i++)
if (buf[i] != 0)
return S_FALSE;
}
const Byte *p = buf + kHeaderPadSize;
UInt32 buf32[kHfsHeaderSize / 4];
RINOK(ReadStream_FALSE(inStream, buf32, kHfsHeaderSize))
const Byte *p = (const Byte *)buf32 + kHeaderPadSize;
CVolHeader &h = Header;
h.Header[0] = p[0];
h.Header[1] = p[1];
if (p[0] == 'B' && p[1] == 'D')
if (GetUi16a(p) == k_Signature_LE16_HFS_BD)
{
/*
It's header for old HFS format.
We don't support old HFS format, but we support
special HFS volume that contains embedded HFS+ volume
special HFS volume that contains embedded HFS+ volume.
HFS MDB : Master directory block
HFS VIB : Volume information block
some old images contain boot data with "LK" signature at start of buf32.
*/
if (p[0x7C] != 'H' || p[0x7C + 1] != '+')
#if 1
// here we check first bytes of archive,
// because start data can contain signature of some another
// archive type that could have priority over HFS.
const void *buf_ptr = (const void *)buf32;
const unsigned sig = GetUi16a(buf_ptr);
if (sig != 'L' + ((unsigned)'K' << 8))
{
// some old HFS (non HFS+) files have no "LK" signature,
// but have non-zero data after 2 first bytes in start 1 KiB.
if (sig != 0)
return S_FALSE;
/*
for (unsigned i = 0; i < kHeaderPadSize / 4; i++)
if (buf32[i] != 0)
return S_FALSE;
*/
}
#endif
if (GetUi16a(p + 0x7c) != k_Signature_LE16_HPLUS) // signature of embedded HFS+ volume
return S_FALSE;
/*
h.CTime = Get32(p + 0x2);
h.MTime = Get32(p + 0x6);
@ -1399,80 +1409,104 @@ HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress)
h.NumFreeBlocks = Get16(p + 0x22);
*/
UInt32 blockSize = Get32(p + 0x14);
{
unsigned i;
for (i = 9; ((UInt32)1 << i) != blockSize; i++)
if (i == 31)
return S_FALSE;
h.BlockSizeLog = i;
}
h.NumBlocks = Get16(p + 0x12);
// v24.09: blockSize in old HFS image can be non-power of 2.
const UInt32 blockSize = Get32a(p + 0x14); // drAlBlkSiz
if (blockSize == 0 || (blockSize & 0x1ff))
return S_FALSE;
const unsigned numBlocks = Get16a(p + 0x12); // drNmAlBlks
// UInt16 drFreeBks = Get16a(p + 0x22); // number of unused allocation blocks
/*
we suppose that it has the follwing layout
we suppose that it has the following layout:
{
start block with header
[h.NumBlocks]
end block with header
start data with header
blocks[h.NumBlocks]
end data with header (probably size_of_footer <= blockSize).
}
*/
PhySize2 = ((UInt64)h.NumBlocks + 2) << h.BlockSizeLog;
UInt32 startBlock = Get16(p + 0x7C + 2);
UInt32 blockCount = Get16(p + 0x7C + 4);
SpecOffset = (UInt64)(1 + startBlock) << h.BlockSizeLog;
UInt64 phy = SpecOffset + ((UInt64)blockCount << h.BlockSizeLog);
// PhySize2 = ((UInt64)numBlocks + 2) * blockSize;
const unsigned sector_of_FirstBlock = Get16a(p + 0x1c); // drAlBlSt : first allocation block in volume
const UInt32 startBlock = Get16a(p + 0x7c + 2);
const UInt32 blockCount = Get16a(p + 0x7c + 4);
SpecOffset = (UInt32)sector_of_FirstBlock << 9; // it's 32-bit here
PhySize2 = SpecOffset + (UInt64)numBlocks * blockSize;
SpecOffset += (UInt64)startBlock * blockSize;
// before v24.09: // SpecOffset = (UInt64)(1 + startBlock) * blockSize;
const UInt64 phy = SpecOffset + (UInt64)blockCount * blockSize;
if (PhySize2 < phy)
PhySize2 = phy;
PhySize2 = phy;
UInt32 tail = 1 << 10; // at least 1 KiB tail (for footer MDB) is expected.
if (tail < blockSize)
tail = blockSize;
RINOK(InStream_GetSize_SeekToEnd(inStream, ArcFileSize))
if (ArcFileSize > PhySize2 &&
ArcFileSize - PhySize2 <= tail)
{
// data after blocks[h.NumBlocks] must contain another copy of MDB.
// In example where blockSize is not power of 2, we have
// (ArcFileSize - PhySize2) < blockSize.
// We suppose that data after blocks[h.NumBlocks] is part of HFS archive.
// Maybe we should scan for footer MDB data (in last 1 KiB)?
PhySize2 = ArcFileSize;
}
RINOK(InStream_SeekSet(inStream, SpecOffset))
RINOK(ReadStream_FALSE(inStream, buf, kHfsHeaderSize))
RINOK(ReadStream_FALSE(inStream, buf32, kHfsHeaderSize))
}
if (p[0] != 'H' || (p[1] != '+' && p[1] != 'X'))
return S_FALSE;
h.Version = Get16(p + 2);
if (h.Version < 4 || h.Version > 5)
return S_FALSE;
// h.Attr = Get32(p + 4);
// h.LastMountedVersion = Get32(p + 8);
// h.JournalInfoBlock = Get32(p + 0xC);
h.CTime = Get32(p + 0x10);
h.MTime = Get32(p + 0x14);
// h.BackupTime = Get32(p + 0x18);
// h.CheckedTime = Get32(p + 0x1C);
h.NumFiles = Get32(p + 0x20);
h.NumFolders = Get32(p + 0x24);
if (h.NumFolders > ((UInt32)1 << 29) ||
h.NumFiles > ((UInt32)1 << 30))
return S_FALSE;
RINOK(InStream_GetSize_SeekToEnd(inStream, ArcFileSize))
if (progress)
// HFS+ / HFSX volume header (starting from offset==1024):
{
const UInt64 numFiles = (UInt64)h.NumFiles + h.NumFolders + 1;
RINOK(progress->SetTotal(&numFiles, NULL))
// v24.09: we use strict condition test for pair signature(Version):
// H+(4), HX(5):
const UInt32 sig = GetUi32a(p);
// h.Version = Get16(p + 2);
h.Is_Hsfx_ver5 = false;
if (sig != k_Signature_LE32_HFSP_VER4)
{
if (sig != k_Signature_LE32_HFSX_VER5)
return S_FALSE;
h.Is_Hsfx_ver5 = true;
}
}
UInt32 blockSize = Get32(p + 0x28);
{
const UInt32 blockSize = Get32a(p + 0x28);
unsigned i;
for (i = 9; ((UInt32)1 << i) != blockSize; i++)
if (i == 31)
return S_FALSE;
h.BlockSizeLog = i;
}
#if 1
// HFS Plus DOCs: The first 1024 bytes are reserved for use as boot blocks
// v24.09: we don't check starting 1 KiB before old (HFS MDB) block ("BD" signture) .
// but we still check starting 1 KiB before HFS+ / HFSX volume header.
// are there HFS+ / HFSX images with non-zero data in this reserved area?
{
for (unsigned i = 0; i < kHeaderPadSize / 4; i++)
if (buf32[i] != 0)
return S_FALSE;
}
#endif
// h.Attr = Get32a(p + 4);
// h.LastMountedVersion = Get32a(p + 8);
// h.JournalInfoBlock = Get32a(p + 0xC);
h.CTime = Get32a(p + 0x10);
h.MTime = Get32a(p + 0x14);
// h.BackupTime = Get32a(p + 0x18);
// h.CheckedTime = Get32a(p + 0x1C);
h.NumFiles = Get32a(p + 0x20);
h.NumFolders = Get32a(p + 0x24);
if (h.NumFolders > ((UInt32)1 << 29) ||
h.NumFiles > ((UInt32)1 << 30))
return S_FALSE;
h.NumBlocks = Get32(p + 0x2C);
h.NumFreeBlocks = Get32(p + 0x30);
RINOK(InStream_GetSize_SeekToEnd(inStream, ArcFileSize))
if (progress)
{
const UInt64 numFiles = (UInt64)h.NumFiles + h.NumFolders + 1;
RINOK(progress->SetTotal(&numFiles, NULL))
}
h.NumBlocks = Get32a(p + 0x2C);
h.NumFreeBlocks = Get32a(p + 0x30);
/*
h.NextCalatlogNodeID = Get32(p + 0x40);
h.WriteCount = Get32(p + 0x44);
@ -1495,7 +1529,7 @@ HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress)
HeadersError = true;
else
{
HRESULT res = LoadExtentFile(extentsFork, inStream, overflowExtents);
const HRESULT res = LoadExtentFile(extentsFork, inStream, overflowExtents);
if (res == S_FALSE)
HeadersError = true;
else if (res != S_OK)
@ -1515,7 +1549,7 @@ HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress)
RINOK(LoadCatalog(catalogFork, overflowExtents, inStream, progress))
PhySize = Header.GetPhySize();
// PhySize = Header.GetPhySize();
return S_OK;
}
@ -1591,7 +1625,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
case kpidCharacts: MethodsMaskToProp(MethodsMask, prop); break;
case kpidPhySize:
{
UInt64 v = SpecOffset + PhySize;
UInt64 v = SpecOffset + Header.GetPhySize(); // PhySize;
if (v < PhySize2)
v = PhySize2;
prop = v;
@ -2529,7 +2563,7 @@ HRESULT CHandler::GetForkStream(const CFork &fork, ISequentialInStream **stream)
return S_FALSE;
}
CSeekExtent se;
se.Phy = (UInt64)e.Pos << Header.BlockSizeLog;
se.Phy = SpecOffset + ((UInt64)e.Pos << Header.BlockSizeLog);
se.Virt = virt;
virt += cur;
rem -= cur;
@ -2540,7 +2574,7 @@ HRESULT CHandler::GetForkStream(const CFork &fork, ISequentialInStream **stream)
return S_FALSE;
CSeekExtent se;
se.Phy = 0;
se.Phy = 0; // = SpecOffset ?
se.Virt = virt;
extentStream->Extents.Add(se);
extentStream->Stream = _stream;

View file

@ -460,9 +460,11 @@ struct LpMetadataHeader
static bool CheckSha256(const Byte *data, size_t size, const Byte *checksum)
{
MY_ALIGN (16)
CSha256 sha;
Sha256_Init(&sha);
Sha256_Update(&sha, data, size);
MY_ALIGN (16)
Byte calced[32];
Sha256_Final(&sha, calced);
return memcmp(checksum, calced, 32) == 0;
@ -470,6 +472,7 @@ static bool CheckSha256(const Byte *data, size_t size, const Byte *checksum)
static bool CheckSha256_csOffset(Byte *data, size_t size, unsigned hashOffset)
{
MY_ALIGN (4)
Byte checksum[32];
Byte *shaData = &data[hashOffset];
memcpy(checksum, shaData, 32);
@ -528,6 +531,7 @@ HRESULT CHandler::Open2(IInStream *stream)
{
RINOK(InStream_SeekSet(stream, LP_PARTITION_RESERVED_BYTES))
{
MY_ALIGN (4)
Byte buf[k_Geometry_Size];
RINOK(ReadStream_FALSE(stream, buf, k_Geometry_Size))
if (memcmp(buf, k_Signature, k_SignatureSize) != 0)

View file

@ -473,8 +473,8 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
break;
}
case kpidIsDir: prop = item.IsDir(); break;
case kpidSize: prop = item.Size; break;
case kpidPackSize: prop = item.PackSize; break;
case kpidSize: prop = (UInt64)item.Size; break;
case kpidPackSize: prop = (UInt64)item.PackSize; break;
case kpidCRC: prop = (UInt32)item.CRC; break;
case kpidHostOS: PAIR_TO_PROP(g_OsPairs, item.OsId, prop); break;
case kpidMTime:

View file

@ -180,9 +180,32 @@ struct CDirLink
}
};
// IMAGE_DIRECTORY_ENTRY_*
static const char * const g_Dir_Names[] =
{
"EXPORT"
, "IMPORT"
, "RESOURCE"
, "EXCEPTION"
, "SECURITY"
, "BASERELOC"
, "DEBUG"
, "ARCHITECTURE" // "COPYRIGHT"
, "GLOBALPTR"
, "TLS"
, "LOAD_CONFIG"
, "BOUND_IMPORT"
, "IAT"
, "DELAY_IMPORT"
, "COM_DESCRIPTOR"
};
enum
{
kDirLink_EXCEPTION = 3,
kDirLink_Certificate = 4,
kDirLink_BASERELOC = 5,
kDirLink_Debug = 6
};
@ -229,7 +252,7 @@ struct COptHeader
UInt32 UninitDataSize;
// UInt32 AddressOfEntryPoint;
// UInt32 BaseOfCode;
// UInt32 BaseOfCode; // VA(.text) == 0x1000 in most cases
// UInt32 BaseOfData32;
UInt64 ImageBase;
@ -273,6 +296,7 @@ struct COptHeader
}
};
// size is 16-bit
bool COptHeader::Parse(const Byte *p, UInt32 size)
{
if (size < k_OptHeader32_Size_MIN)
@ -334,14 +358,18 @@ bool COptHeader::Parse(const Byte *p, UInt32 size)
pos = 92;
}
G32(pos, NumDirItems);
if (NumDirItems > (1 << 16))
UInt32 numDirItems;
G32(pos, numDirItems);
NumDirItems = numDirItems;
if (numDirItems > (1 << 13))
return false;
pos += 4;
if (pos + 8 * NumDirItems > size)
if (pos + 8 * numDirItems > size)
return false;
memset((void *)DirItems, 0, sizeof(DirItems));
for (UInt32 i = 0; i < NumDirItems && i < kNumDirItemsMax; i++)
if (numDirItems > kNumDirItemsMax)
numDirItems = kNumDirItemsMax;
for (UInt32 i = 0; i < numDirItems; i++)
DirItems[i].Parse(p + pos + i * 8);
return true;
}
@ -352,27 +380,41 @@ struct CSection
{
AString Name;
UInt32 ExtractSize;
UInt32 VSize;
UInt32 Va;
UInt32 PSize;
UInt32 Pa;
UInt32 Flags;
UInt32 Time;
// UInt16 NumRelocs;
// UInt16 NumRelocs; // is set to zero for executable images
bool IsRealSect;
bool IsDebug;
bool IsAdditionalSection;
CSection(): IsRealSect(false), IsDebug(false), IsAdditionalSection(false) {}
CSection():
ExtractSize(0),
IsRealSect(false),
IsDebug(false),
IsAdditionalSection(false)
// , NumRelocs(0)
{}
UInt32 GetSizeExtract() const { return PSize; }
UInt32 GetSizeMin() const { return MyMin(PSize, VSize); }
void Set_Size_for_all(UInt32 size)
{
PSize = VSize = ExtractSize = size;
}
UInt32 GetSize_Extract() const
{
return ExtractSize;
}
void UpdateTotalSize(UInt32 &totalSize) const
{
UInt32 t = Pa + PSize;
const UInt32 t = Pa + PSize;
if (totalSize < t)
totalSize = t;
totalSize = t;
}
void Parse(const Byte *p);
@ -380,8 +422,8 @@ struct CSection
int Compare(const CSection &s) const
{
RINOZ(MyCompare(Pa, s.Pa))
UInt32 size1 = GetSizeExtract();
UInt32 size2 = s.GetSizeExtract();
const UInt32 size1 = GetSize_Extract();
const UInt32 size2 = s.GetSize_Extract();
return MyCompare(size1, size2);
}
};
@ -402,6 +444,10 @@ void CSection::Parse(const Byte *p)
G32(20, Pa);
// G16(32, NumRelocs);
G32(36, Flags);
// v24.08: we extract only useful data (without extra padding bytes).
// VSize == 0 is not expected, but we support that case too.
// return (VSize && VSize < PSize) ? VSize : PSize;
ExtractSize = (VSize && VSize < PSize) ? VSize : PSize;
}
@ -508,6 +554,7 @@ static const CUInt32PCharPair g_MachinePairs[] =
{ 0x01D3, "AM33" },
{ 0x01F0, "PPC" },
{ 0x01F1, "PPC-FP" },
{ 0x01F2, "PPC-BE" },
{ 0x0200, "IA-64" },
{ 0x0266, "MIPS-16" },
{ 0x0284, "Alpha-64" },
@ -830,11 +877,11 @@ enum
kpidStackReserve,
kpidStackCommit,
kpidHeapReserve,
kpidHeapCommit,
kpidImageBase
// kpidAddressOfEntryPoint,
// kpidBaseOfCode,
// kpidBaseOfData32,
kpidHeapCommit
// , kpidImageBase
// , kpidAddressOfEntryPoint
// , kpidBaseOfCode
// , kpidBaseOfData32
};
static const CStatProp kArcProps[] =
@ -864,14 +911,16 @@ static const CStatProp kArcProps[] =
{ "Stack Commit", kpidStackCommit, VT_UI8},
{ "Heap Reserve", kpidHeapReserve, VT_UI8},
{ "Heap Commit", kpidHeapCommit, VT_UI8},
{ "Image Base", kpidImageBase, VT_UI8},
{ NULL, kpidComment, VT_BSTR},
{ NULL, kpidVa, VT_UI8 }, // "Image Base", kpidImageBase, VT_UI8
{ NULL, kpidComment, VT_BSTR}
// { "Address Of Entry Point", kpidAddressOfEntryPoint, VT_UI8},
// { "Base Of Code", kpidBaseOfCode, VT_UI8},
// { "Base Of Data", kpidBaseOfData32, VT_UI8},
// , { "Address Of Entry Point", kpidAddressOfEntryPoint, VT_UI8}
// , { "Base Of Code", kpidBaseOfCode, VT_UI8}
// , { "Base Of Data", kpidBaseOfData32, VT_UI8}
};
// #define kpid_NumRelocs 250
static const Byte kProps[] =
{
kpidPath,
@ -880,7 +929,8 @@ static const Byte kProps[] =
kpidVirtualSize,
kpidCharacts,
kpidOffset,
kpidVa,
kpidVa
// , kpid_NumRelocs
};
IMP_IInArchive_Props
@ -899,7 +949,42 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
switch (propID)
{
case kpidPhySize: prop = _totalSize; break;
case kpidComment: if (!_versionFullString.IsEmpty()) prop = _versionFullString; break;
case kpidComment:
{
UString s (_versionFullString);
s.Add_LF();
s += "Data Directories: ";
s.Add_UInt32(_optHeader.NumDirItems);
s.Add_LF();
s.Add_Char('{');
s.Add_LF();
for (unsigned i = 0; i < _optHeader.NumDirItems
&& i < Z7_ARRAY_SIZE(_optHeader.DirItems); i++)
{
const CDirLink &di = _optHeader.DirItems[i];
if (di.Va == 0 && di.Size == 0)
continue;
s += "index=";
s.Add_UInt32(i);
if (i < Z7_ARRAY_SIZE(g_Dir_Names))
{
s += " name=";
s += g_Dir_Names[i];
}
s += " VA=0x";
char temp[16];
ConvertUInt32ToHex(di.Va, temp);
s += temp;
s += " Size=";
s.Add_UInt32(di.Size);
s.Add_LF();
}
s.Add_Char('}');
s.Add_LF();
prop = s;
break;
}
case kpidShortComment:
if (!_versionShortString.IsEmpty())
prop = _versionShortString;
@ -969,8 +1054,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
case kpidStackCommit: prop = _optHeader.StackCommit; break;
case kpidHeapReserve: prop = _optHeader.HeapReserve; break;
case kpidHeapCommit: prop = _optHeader.HeapCommit; break;
case kpidImageBase: prop = _optHeader.ImageBase; break;
case kpidVa: prop = _optHeader.ImageBase; break; // kpidImageBase:
// case kpidAddressOfEntryPoint: prop = _optHeader.AddressOfEntryPoint; break;
// case kpidBaseOfCode: prop = _optHeader.BaseOfCode; break;
// case kpidBaseOfData32: if (!_optHeader.Is64Bit()) prop = _optHeader.BaseOfData32; break;
@ -1130,7 +1214,8 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop = MultiByteToUnicodeString(s);
break;
}
case kpidSize: prop = (UInt64)item.PSize; break;
case kpidSize: prop = (UInt64)item.GetSize_Extract(); break;
// case kpid_NumRelocs: prop = (UInt32)item.NumRelocs; break;
case kpidPackSize: prop = (UInt64)item.PSize; break;
case kpidVirtualSize: prop = (UInt64)item.VSize; break;
case kpidOffset: prop = item.Pa; break;
@ -1229,7 +1314,7 @@ HRESULT CHandler::LoadDebugSections(IInStream *stream, bool &thereIsSection)
sect.Time = de.Time;
sect.Va = de.Va;
sect.Pa = de.Pa;
sect.PSize = sect.VSize = de.Size;
sect.Set_Size_for_all(de.Size);
}
buf += kEntrySize;
}
@ -1757,7 +1842,7 @@ static void CopyToUString(const Byte *p, UString &s)
{
for (;;)
{
wchar_t c = (wchar_t)Get16(p);
const wchar_t c = (wchar_t)Get16(p);
p += 2;
if (c == 0)
return;
@ -1765,6 +1850,16 @@ static void CopyToUString(const Byte *p, UString &s)
}
}
static void CopyToUString_ByLen16(const Byte *p, unsigned numChars16, UString &s)
{
for (; numChars16; numChars16--)
{
const wchar_t c = (wchar_t)Get16(p);
p += 2;
s += c;
}
}
static bool CompareWStrStrings(const Byte *p, const char *s)
{
unsigned pos = 0;
@ -1783,7 +1878,7 @@ struct CVersionBlock
{
UInt32 TotalLen;
UInt32 ValueLen;
bool IsTextValue;
unsigned IsTextValue;
unsigned StrSize;
bool Parse(const Byte *p, UInt32 size);
@ -1802,6 +1897,23 @@ static int Get_Utf16Str_Len_InBytes(const Byte *p, size_t size)
}
}
static int Get_Utf16Str_Len_InBytes_AllowNonZeroTail(const Byte *p, size_t size)
{
unsigned pos = 0;
for (;;)
{
if (pos + 1 >= size)
{
if (pos == size)
return (int)pos;
return -1;
}
if (Get16(p + pos) == 0)
return (int)pos;
pos += 2;
}
}
static const unsigned k_ResoureBlockHeader_Size = 6;
bool CVersionBlock::Parse(const Byte *p, UInt32 size)
@ -1812,14 +1924,12 @@ bool CVersionBlock::Parse(const Byte *p, UInt32 size)
ValueLen = Get16(p + 2);
if (TotalLen < k_ResoureBlockHeader_Size || TotalLen > size)
return false;
switch (Get16(p + 4))
{
case 0: IsTextValue = false; break;
case 1: IsTextValue = true; break;
default: return false;
}
IsTextValue = Get16(p + 4);
if (IsTextValue > 1)
return false;
StrSize = 0;
const int t = Get_Utf16Str_Len_InBytes(p + k_ResoureBlockHeader_Size, TotalLen - k_ResoureBlockHeader_Size);
const int t = Get_Utf16Str_Len_InBytes(p + k_ResoureBlockHeader_Size,
TotalLen - k_ResoureBlockHeader_Size);
if (t < 0)
return false;
StrSize = (unsigned)t;
@ -1859,7 +1969,7 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
// if (size != vb.TotalLen) return false;
*/
if (size > vb.TotalLen)
size = vb.TotalLen;
size = vb.TotalLen;
CMy_VS_FIXEDFILEINFO FixedFileInfo;
if (!FixedFileInfo.Parse(p + pos))
return false;
@ -1880,7 +1990,7 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
return false;
if (vb.ValueLen != 0)
return false;
UInt32 endPos = pos + vb.TotalLen;
const UInt32 endPos = pos + vb.TotalLen;
pos += k_ResoureBlockHeader_Size;
f.AddSpaces(2);
@ -1901,7 +2011,7 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
CVersionBlock vb2;
if (!vb2.Parse(p + pos, endPos - pos))
return false;
UInt32 endPos2 = pos + vb2.TotalLen;
const UInt32 endPos2 = pos + vb2.TotalLen;
if (vb2.IsTextValue)
return false;
pos += k_ResoureBlockHeader_Size;
@ -1919,9 +2029,9 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
UInt32 num = (vb2.ValueLen >> 2);
for (; num != 0; num--, pos += 4)
{
UInt32 dw = Get32(p + pos);
UInt32 lang = LOWORD(dw);
UInt32 codePage = HIWORD(dw);
const UInt32 dw = Get32(p + pos);
const UInt32 lang = LOWORD(dw);
const UInt32 codePage = HIWORD(dw);
f.AddString(", ");
PrintHex(f, lang);
@ -1936,7 +2046,6 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
if (!CompareWStrStrings(p + pos, "StringFileInfo"))
return false;
pos += vb.StrSize + 2;
for (;;)
{
pos += (4 - pos) & 3;
@ -1945,7 +2054,7 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
CVersionBlock vb2;
if (!vb2.Parse(p + pos, endPos - pos))
return false;
UInt32 endPos2 = pos + vb2.TotalLen;
const UInt32 endPos2 = pos + vb2.TotalLen;
if (vb2.ValueLen != 0)
return false;
pos += k_ResoureBlockHeader_Size;
@ -1967,9 +2076,8 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
CVersionBlock vb3;
if (!vb3.Parse(p + pos, endPos2 - pos))
return false;
// ValueLen sometimes is a number of characters (not bytes)?
// So we don't use it.
UInt32 endPos3 = pos + vb3.TotalLen;
// ValueLen is a number of 16-bit characters (usually it includes zero tail character).
const UInt32 endPos3 = pos + vb3.TotalLen;
pos += k_ResoureBlockHeader_Size;
// we don't write string if it's not text
@ -1984,26 +2092,35 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
pos += vb3.StrSize + 2;
pos += (4 - pos) & 3;
if (vb3.ValueLen > 0 && pos + 2 <= endPos3)
if (vb3.ValueLen != 0 && pos /* + 2 */ <= endPos3)
{
f.AddChar(',');
f.AddSpaces((34 - (int)vb3.StrSize) / 2);
const int sLen = Get_Utf16Str_Len_InBytes(p + pos, endPos3 - pos);
// vb3.TotalLen for some PE files (not from msvc) doesn't include tail zero at the end of Value string.
// we allow that minor error.
const int sLen = Get_Utf16Str_Len_InBytes_AllowNonZeroTail(p + pos, endPos3 - pos);
if (sLen < 0)
return false;
/*
if (vb3.ValueLen - 1 != (unsigned)sLen / 2 &&
vb3.ValueLen != (unsigned)sLen / 2)
return false;
*/
AddParamString(f, p + pos, (unsigned)sLen);
CopyToUString(p + pos, value);
pos += (unsigned)sLen + 2;
CopyToUString_ByLen16(p + pos, (unsigned)sLen / 2, value);
// pos += (unsigned)sLen + 2;
}
AddToUniqueUStringVector(keys, key, value);
}
pos = endPos3;
f.NewLine();
}
pos = endPos2;
f.CloseBlock(4);
}
}
f.CloseBlock(2);
pos = endPos;
}
f.CloseBlock(0);
@ -2218,7 +2335,7 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi
if (sect2.PSize != 0)
{
sect2.VSize = sect2.PSize;
sect2.ExtractSize = sect2.VSize = sect2.PSize;
sect2.Name = ".rsrc_1";
sect2.Time = 0;
sect2.IsAdditionalSection = true;
@ -2337,6 +2454,20 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
CSection &sect = _sections.AddNew();
sect.Parse(buffer + pos);
sect.IsRealSect = true;
if (sect.Name.IsEqualTo(".reloc"))
{
const CDirLink &dl = _optHeader.DirItems[kDirLink_BASERELOC];
if (dl.Va == sect.Va &&
dl.Size <= sect.PSize)
sect.ExtractSize = dl.Size;
}
else if (sect.Name.IsEqualTo(".pdata"))
{
const CDirLink &dl = _optHeader.DirItems[kDirLink_EXCEPTION];
if (dl.Va == sect.Va &&
dl.Size <= sect.PSize)
sect.ExtractSize = dl.Size;
}
/* PE pre-file in .hxs file has errors:
PSize of resource is larger than real size.
@ -2390,7 +2521,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
sect.Name = "CERTIFICATE";
sect.Va = 0;
sect.Pa = certLink.Va;
sect.PSize = sect.VSize = certLink.Size;
sect.Set_Size_for_all(certLink.Size);
sect.UpdateTotalSize(_totalSize);
}
@ -2448,7 +2579,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
sect.Name = "COFF_SYMBOLS";
sect.Va = 0;
sect.Pa = _header.PointerToSymbolTable;
sect.PSize = sect.VSize = size;
sect.Set_Size_for_all(size);
sect.UpdateTotalSize(_totalSize);
}
@ -2464,11 +2595,11 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
{
CSection &s2 = _sections.AddNew();
s2.Pa = s2.Va = limit;
s2.PSize = s2.VSize = s.Pa - limit;
s2.Set_Size_for_all(s.Pa - limit);
s2.IsAdditionalSection = true;
s2.Name = '[';
s2.Name.Add_Char('[');
s2.Name.Add_UInt32(num++);
s2.Name += ']';
s2.Name.Add_Char(']');
limit = s.Pa;
}
UInt32 next = s.Pa + s.PSize;
@ -2700,29 +2831,26 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
else if (mixItem.ResourceIndex >= 0)
size = _items[mixItem.ResourceIndex].GetSize();
else
size = _sections[mixItem.SectionIndex].GetSizeExtract();
size = _sections[mixItem.SectionIndex].GetSize_Extract();
totalSize += size;
}
extractCallback->SetTotal(totalSize);
RINOK(extractCallback->SetTotal(totalSize))
UInt64 currentTotalSize = 0;
CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
lps->Init(extractCallback, false);
CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
inStream->SetStream(_stream);
totalSize = 0;
UInt64 currentItemSize;
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false);
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
CMyComPtr<ISequentialInStream> inStream(streamSpec);
streamSpec->SetStream(_stream);
for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
for (i = 0;; i++, totalSize += currentItemSize)
{
lps->InSize = lps->OutSize = currentTotalSize;
lps->InSize = lps->OutSize = totalSize;
RINOK(lps->SetCur())
if (i >= numItems)
break;
const Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
@ -2776,15 +2904,15 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
else
{
currentItemSize = sect.GetSizeExtract();
currentItemSize = sect.GetSize_Extract();
if (!testMode && !outStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode))
RINOK(InStream_SeekSet(_stream, sect.Pa))
streamSpec->Init(currentItemSize);
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress))
isOk = (copyCoderSpec->TotalSize == currentItemSize);
inStream->Init(currentItemSize);
RINOK(copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps))
isOk = (copyCoder->TotalSize == currentItemSize);
}
outStream.Release();
@ -2804,7 +2932,7 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
const CMixItem &mixItem = _mixItems[index];
const CSection &sect = _sections[mixItem.SectionIndex];
if (mixItem.IsSectionItem())
return CreateLimitedInStream(_stream, sect.Pa, sect.PSize, stream);
return CreateLimitedInStream(_stream, sect.Pa, sect.GetSize_Extract(), stream);
CBufInStream *inStreamSpec = new CBufInStream;
CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;
@ -2964,7 +3092,7 @@ bool CHeader::Parse(const Byte *p)
G32(12, BaseOfCode);
G64(16, ImageBase);
*/
for (int i = 0; i < 2; i++)
for (unsigned i = 0; i < 2; i++)
{
CDataDir &dd = DataDir[i];
dd.Parse(p + 24 + i * 8);
@ -2997,6 +3125,7 @@ struct CSection
{
Byte Name[NPe::kNameSize];
UInt32 ExtractSize;
UInt32 VSize;
UInt32 Va;
UInt32 PSize;
@ -3013,6 +3142,7 @@ struct CSection
G32(20, Pa);
// G32(p + 32, NumRelocs);
G32(36, Flags);
ExtractSize = (VSize && VSize < PSize) ? VSize : PSize;
}
bool Check() const
@ -3022,11 +3152,16 @@ struct CSection
PSize <= ((UInt32)1 << 30);
}
UInt32 GetSize_Extract() const
{
return ExtractSize;
}
void UpdateTotalSize(UInt32 &totalSize)
{
UInt32 t = Pa + PSize;
if (t > totalSize)
totalSize = t;
const UInt32 t = Pa + PSize;
if (totalSize < t)
totalSize = t;
}
};
@ -3050,6 +3185,7 @@ static const Byte kProps[] =
{
kpidPath,
kpidSize,
kpidPackSize,
kpidVirtualSize,
kpidCharacts,
kpidOffset,
@ -3108,7 +3244,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop = MultiByteToUnicodeString(name);
break;
}
case kpidSize:
case kpidSize: prop = (UInt64)item.GetSize_Extract(); break;
case kpidPackSize: prop = (UInt64)item.PSize; break;
case kpidVirtualSize: prop = (UInt64)item.VSize; break;
case kpidOffset: prop = item.Pa; break;
@ -3168,13 +3304,13 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *inStream,
{
COM_TRY_BEGIN
Close();
try
// try
{
if (Open2(inStream) != S_OK)
return S_FALSE;
_stream = inStream;
}
catch(...) { return S_FALSE; }
// catch(...) { return S_FALSE; }
return S_OK;
COM_TRY_END
}
@ -3205,26 +3341,25 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UInt64 totalSize = 0;
UInt32 i;
for (i = 0; i < numItems; i++)
totalSize += _items[allFilesMode ? i : indices[i]].PSize;
extractCallback->SetTotal(totalSize);
totalSize += _items[allFilesMode ? i : indices[i]].GetSize_Extract();
RINOK(extractCallback->SetTotal(totalSize))
UInt64 currentTotalSize = 0;
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
lps->Init(extractCallback, false);
CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
inStream->SetStream(_stream);
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
CMyComPtr<ISequentialInStream> inStream(streamSpec);
streamSpec->SetStream(_stream);
totalSize = 0;
for (i = 0; i < numItems; i++)
for (i = 0;; i++)
{
lps->InSize = lps->OutSize = currentTotalSize;
lps->InSize = lps->OutSize = totalSize;
RINOK(lps->SetCur())
if (i >= numItems)
break;
int opRes;
{
CMyComPtr<ISequentialOutStream> realOutStream;
const Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
@ -3232,21 +3367,22 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
const UInt32 index = allFilesMode ? i : indices[i];
const CSection &item = _items[index];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
currentTotalSize += item.PSize;
const UInt32 size = item.GetSize_Extract();
totalSize += size;
if (!testMode && !realOutStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode))
int res = NExtract::NOperationResult::kDataError;
RINOK(InStream_SeekSet(_stream, item.Pa))
streamSpec->Init(item.PSize);
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress))
if (copyCoderSpec->TotalSize == item.PSize)
res = NExtract::NOperationResult::kOK;
inStream->Init(size);
RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))
realOutStream.Release();
RINOK(extractCallback->SetOperationResult(res))
opRes = (copyCoder->TotalSize == size) ?
NExtract::NOperationResult::kOK : (copyCoder->TotalSize < size) ?
NExtract::NOperationResult::kUnexpectedEnd :
NExtract::NOperationResult::kDataError;
}
RINOK(extractCallback->SetOperationResult(opRes))
}
return S_OK;
COM_TRY_END
@ -3256,7 +3392,7 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
{
COM_TRY_BEGIN
const CSection &item = _items[index];
return CreateLimitedInStream(_stream, item.Pa, item.PSize, stream);
return CreateLimitedInStream(_stream, item.Pa, item.GetSize_Extract(), stream);
COM_TRY_END
}

View file

@ -11,6 +11,7 @@
#include "../../Common/MyBuffer2.h"
#include "../../Windows/PropVariant.h"
#include "../../Windows/PropVariantUtils.h"
#include "../Common/RegisterArc.h"
#include "../Common/StreamObjects.h"
@ -20,8 +21,8 @@
#include "HandlerCont.h"
#define Get32(p) GetBe32(p)
#define Get64(p) GetBe64(p)
#define Get32(p) GetBe32a(p)
#define Get64(p) GetBe64a(p)
using namespace NWindows;
@ -32,9 +33,9 @@ static const Byte k_Signature[] = { 'Q', 'F', 'I', 0xFB, 0, 0, 0 };
/*
VA to PA maps:
high bits (L1) : : in L1 Table : the reference to L1 Table
mid bits (L2) : _numMidBits : in L2 Table : the reference to cluster
low bits : _clusterBits
high bits (L1) : : index in L1 (_dir) : _dir[high_index] points to Table.
mid bits (L2) : _numMidBits : index in Table, Table[index] points to cluster start offset in arc file.
low bits : _clusterBits : offset inside cluster.
*/
Z7_class_CHandler_final: public CHandlerImg
@ -49,30 +50,27 @@ Z7_class_CHandler_final: public CHandlerImg
CObjArray2<UInt32> _dir;
CAlignedBuffer _table;
UInt64 _cacheCluster;
CByteBuffer _cache;
CByteBuffer _cacheCompressed;
UInt64 _cacheCluster;
UInt64 _comprPos;
size_t _comprSize;
UInt64 _phySize;
CBufInStream *_bufInStreamSpec;
CMyComPtr<ISequentialInStream> _bufInStream;
CBufPtrSeqOutStream *_bufOutStreamSpec;
CMyComPtr<ISequentialOutStream> _bufOutStream;
NCompress::NDeflate::NDecoder::CCOMCoder *_deflateDecoderSpec;
CMyComPtr<ICompressCoder> _deflateDecoder;
bool _needDeflate;
bool _needCompression;
bool _isArc;
bool _unsupported;
Byte _compressionType;
UInt64 _phySize;
CMyComPtr2<ISequentialInStream, CBufInStream> _bufInStream;
CMyComPtr2<ISequentialOutStream, CBufPtrSeqOutStream> _bufOutStream;
CMyComPtr2<ICompressCoder, NCompress::NDeflate::NDecoder::CCOMCoder> _deflateDecoder;
UInt32 _version;
UInt32 _cryptMethod;
UInt64 _incompatFlags;
HRESULT Seek2(UInt64 offset)
{
@ -96,13 +94,11 @@ Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
{
if (processedSize)
*processedSize = 0;
// printf("\nRead _virtPos = %6d size = %6d\n", (UInt32)_virtPos, size);
if (_virtPos >= _size)
return S_OK;
{
UInt64 rem = _size - _virtPos;
const UInt64 rem = _size - _virtPos;
if (size > rem)
size = (UInt32)rem;
if (size == 0)
@ -115,47 +111,43 @@ Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
const size_t clusterSize = (size_t)1 << _clusterBits;
const size_t lowBits = (size_t)_virtPos & (clusterSize - 1);
{
size_t rem = clusterSize - lowBits;
const size_t rem = clusterSize - lowBits;
if (size > rem)
size = (UInt32)rem;
}
if (cluster == _cacheCluster)
{
memcpy(data, _cache + lowBits, size);
break;
}
const UInt64 high = cluster >> _numMidBits;
if (high < _dir.Size())
{
const UInt32 tabl = _dir[(unsigned)high];
const UInt32 tabl = _dir[(size_t)high];
if (tabl != kEmptyDirItem)
{
const Byte *buffer = _table + ((size_t)tabl << (_numMidBits + 3));
const size_t midBits = (size_t)cluster & (((size_t)1 << _numMidBits) - 1);
const Byte *p = (const Byte *)buffer + (midBits << 3);
const Byte *p = _table + ((((size_t)tabl << _numMidBits) + midBits) << 3);
UInt64 v = Get64(p);
if (v != 0)
if (v)
{
if ((v & _compressedFlag) != 0)
if (v & _compressedFlag)
{
if (_version <= 1)
return E_FAIL;
/*
the example of table record for 12-bit clusters (4KB uncompressed).
2 bits : isCompressed status
4 bits : num_sectors_minus1; packSize = (num_sectors_minus1 + 1) * 512;
it uses one additional bit over unpacked cluster_bits
49 bits : offset of 512-sector
9 bits : offset in 512-sector
the example of table record for 12-bit clusters (4KB uncompressed):
2 bits : isCompressed status
(4 == _clusterBits - 8) bits : (num_sectors - 1)
packSize = num_sectors * 512;
it uses one additional bit over unpacked cluster_bits.
(49 == 61 - _clusterBits) bits : offset of 512-byte sector
9 bits : offset in 512-byte sector
*/
const unsigned numOffsetBits = (62 - (_clusterBits - 9 + 1));
const unsigned numOffsetBits = 62 - (_clusterBits - 8);
const UInt64 offset = v & (((UInt64)1 << 62) - 1);
const size_t dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9;
UInt64 sectorOffset = offset & (((UInt64)1 << numOffsetBits) - (1 << 9));
@ -167,7 +159,7 @@ Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
if (sectorOffset >= _comprPos && offset2inCache < _comprSize)
{
if (offset2inCache != 0)
if (offset2inCache)
{
_comprSize -= (size_t)offset2inCache;
memmove(_cacheCompressed, _cacheCompressed + (size_t)offset2inCache, _comprSize);
@ -193,39 +185,34 @@ Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
const size_t dataSize3 = dataSize - _comprSize;
size_t dataSize2 = dataSize3;
// printf("\n\n=======\nReadStream = %6d _comprPos = %6d \n", (UInt32)dataSize2, (UInt32)_comprPos);
RINOK(ReadStream(Stream, _cacheCompressed + _comprSize, &dataSize2))
const HRESULT hres = ReadStream(Stream, _cacheCompressed + _comprSize, &dataSize2);
_posInArc += dataSize2;
RINOK(hres)
if (dataSize2 != dataSize3)
return E_FAIL;
_comprSize += dataSize2;
}
const size_t kSectorMask = (1 << 9) - 1;
const size_t offsetInSector = ((size_t)offset & kSectorMask);
_bufInStreamSpec->Init(_cacheCompressed + offsetInSector, dataSize - offsetInSector);
const size_t offsetInSector = (size_t)offset & kSectorMask;
_bufInStream->Init(_cacheCompressed + offsetInSector, dataSize - offsetInSector);
_cacheCluster = (UInt64)(Int64)-1;
if (_cache.Size() < clusterSize)
return E_FAIL;
_bufOutStreamSpec->Init(_cache, clusterSize);
_bufOutStream->Init(_cache, clusterSize);
// Do we need to use smaller block than clusterSize for last cluster?
const UInt64 blockSize64 = clusterSize;
HRESULT res = _deflateDecoder->Code(_bufInStream, _bufOutStream, NULL, &blockSize64, NULL);
HRESULT res = _deflateDecoder.Interface()->Code(_bufInStream, _bufOutStream, NULL, &blockSize64, NULL);
/*
if (_bufOutStreamSpec->GetPos() != clusterSize)
memset(_cache + _bufOutStreamSpec->GetPos(), 0, clusterSize - _bufOutStreamSpec->GetPos());
*/
if (res == S_OK)
if (!_deflateDecoderSpec->IsFinished()
|| _bufOutStreamSpec->GetPos() != clusterSize)
if (!_deflateDecoder->IsFinished()
|| _bufOutStream->GetPos() != clusterSize)
res = S_FALSE;
RINOK(res)
_cacheCluster = cluster;
continue;
/*
memcpy(data, _cache + lowBits, size);
@ -233,17 +220,17 @@ Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
*/
}
// version 3 support zero clusters
// version_3 supports zero clusters
if (((UInt32)v & 511) != 1)
{
v &= (_compressedFlag - 1);
v &= _compressedFlag - 1;
v += lowBits;
if (v != _posInArc)
{
// printf("\n%12I64x\n", v - _posInArc);
RINOK(Seek2(v))
}
HRESULT res = Stream->Read(data, size, &size);
const HRESULT res = Stream->Read(data, size, &size);
_posInArc += size;
_virtPos += size;
if (processedSize)
@ -274,13 +261,25 @@ static const Byte kProps[] =
static const Byte kArcProps[] =
{
kpidClusterSize,
kpidSectorSize, // actually we need variable to show table size
kpidHeadersSize,
kpidUnpackVer,
kpidMethod
kpidMethod,
kpidCharacts
};
IMP_IInArchive_Props
IMP_IInArchive_ArcProps
static const CUInt32PCharPair g_IncompatFlags_Characts[] =
{
{ 0, "Dirty" },
{ 1, "Corrupt" },
{ 2, "External_Data_File" },
{ 3, "Compression" },
{ 4, "Extended_L2" }
};
Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
{
COM_TRY_BEGIN
@ -290,28 +289,54 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
{
case kpidMainSubfile: prop = (UInt32)0; break;
case kpidClusterSize: prop = (UInt32)1 << _clusterBits; break;
case kpidPhySize: if (_phySize != 0) prop = _phySize; break;
case kpidSectorSize: prop = (UInt32)1 << (_numMidBits + 3); break;
case kpidHeadersSize: prop = _table.Size() + (UInt64)_dir.Size() * 8; break;
case kpidPhySize: if (_phySize) prop = _phySize; break;
case kpidUnpackVer: prop = _version; break;
case kpidCharacts:
{
if (_incompatFlags)
{
AString s ("incompatible: ");
// we need to show also high 32-bits.
s += FlagsToString(g_IncompatFlags_Characts,
Z7_ARRAY_SIZE(g_IncompatFlags_Characts), (UInt32)_incompatFlags);
prop = s;
}
break;
}
case kpidMethod:
{
AString s;
if (_needDeflate)
s = "Deflate";
if (_compressionType)
{
if (_compressionType == 1)
s += "ZSTD";
else
{
s += "Compression:";
s.Add_UInt32(_compressionType);
}
}
else if (_needCompression)
s.Add_OptSpaced("Deflate");
if (_cryptMethod != 0)
if (_cryptMethod)
{
s.Add_Space_if_NotEmpty();
if (_cryptMethod == 1)
s += "AES";
if (_cryptMethod == 2)
s += "LUKS";
else
{
s += "Encryption:";
s.Add_UInt32(_cryptMethod);
}
}
if (!s.IsEmpty())
prop = s;
break;
}
@ -321,9 +346,9 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;
// if (_headerError) v |= kpv_ErrorFlags_HeadersError;
if (!Stream && v == 0 && _isArc)
if (!Stream && v == 0)
v = kpv_ErrorFlags_HeadersError;
if (v != 0)
if (v)
prop = v;
break;
}
@ -355,76 +380,91 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN
HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
{
const unsigned kHeaderSize = 18 * 4;
Byte buf[kHeaderSize];
RINOK(ReadStream_FALSE(stream, buf, kHeaderSize))
if (memcmp(buf, k_Signature, 4) != 0)
UInt64 buf64[0x70 / 8];
RINOK(ReadStream_FALSE(stream, buf64, sizeof(buf64)))
const void *buf = (const void *)buf64;
// signature: { 'Q', 'F', 'I', 0xFB }
if (*(const UInt32 *)buf != Z7_CONV_BE_TO_NATIVE_CONST32(0x514649fb))
return S_FALSE;
_version = Get32(buf + 4);
_version = Get32((const Byte *)(const void *)buf64 + 4);
if (_version < 1 || _version > 3)
return S_FALSE;
const UInt64 backOffset = Get64(buf + 8);
// UInt32 backSize = Get32(buf + 0x10);
UInt64 l1Offset;
UInt32 l1Size;
const UInt64 k_UncompressedSize_MAX = (UInt64)1 << 60;
const UInt64 k_CompressedSize_MAX = (UInt64)1 << 60;
_size = Get64((const Byte *)(const void *)buf64 + 0x18);
if (_size > k_UncompressedSize_MAX)
return S_FALSE;
size_t l1Size;
UInt32 headerSize;
if (_version == 1)
{
// _mTime = Get32(buf + 0x14); // is unused im most images
_size = Get64(buf + 0x18);
_clusterBits = buf[0x20];
_numMidBits = buf[0x21];
// _mTime = Get32((const Byte *)(const void *)buf64 + 0x14); // is unused in most images
_clusterBits = ((const Byte *)(const void *)buf64)[0x20];
_numMidBits = ((const Byte *)(const void *)buf64)[0x21];
if (_clusterBits < 9 || _clusterBits > 30)
return S_FALSE;
if (_numMidBits < 1 || _numMidBits > 28)
return S_FALSE;
_cryptMethod = Get32(buf + 0x24);
l1Offset = Get64(buf + 0x28);
if (l1Offset < 0x30)
return S_FALSE;
const unsigned numBits2 = (_clusterBits + _numMidBits);
_cryptMethod = Get32((const Byte *)(const void *)buf64 + 0x24);
const unsigned numBits2 = _clusterBits + _numMidBits;
const UInt64 l1Size64 = (_size + (((UInt64)1 << numBits2) - 1)) >> numBits2;
if (l1Size64 > ((UInt32)1 << 31))
return S_FALSE;
l1Size = (UInt32)l1Size64;
l1Size = (size_t)l1Size64;
headerSize = 0x30;
}
else
{
_clusterBits = Get32(buf + 0x14);
_clusterBits = Get32((const Byte *)(const void *)buf64 + 0x14);
if (_clusterBits < 9 || _clusterBits > 30)
return S_FALSE;
_numMidBits = _clusterBits - 3;
_size = Get64(buf + 0x18);
_cryptMethod = Get32(buf + 0x20);
l1Size = Get32(buf + 0x24);
l1Offset = Get64(buf + 0x28); // must be aligned for cluster
const UInt64 refOffset = Get64(buf + 0x30); // must be aligned for cluster
const UInt32 refClusters = Get32(buf + 0x38);
// UInt32 numSnapshots = Get32(buf + 0x3C);
// UInt64 snapshotsOffset = Get64(buf + 0x40); // must be aligned for cluster
_cryptMethod = Get32((const Byte *)(const void *)buf64 + 0x20);
l1Size = Get32((const Byte *)(const void *)buf64 + 0x24);
headerSize = 0x48;
if (_version >= 3)
{
_incompatFlags = Get64((const Byte *)(const void *)buf64 + 0x48);
// const UInt64 CompatFlags = Get64((const Byte *)(const void *)buf64 + 0x50);
// const UInt64 AutoClearFlags = Get64((const Byte *)(const void *)buf64 + 0x58);
// const UInt32 RefCountOrder = Get32((const Byte *)(const void *)buf64 + 0x60);
headerSize = 0x68;
const UInt32 headerSize2 = Get32((const Byte *)(const void *)buf64 + 0x64);
if (headerSize2 > (1u << 30))
return S_FALSE;
if (headerSize < headerSize2)
headerSize = headerSize2;
if (headerSize2 >= 0x68 + 1)
_compressionType = ((const Byte *)(const void *)buf64)[0x68];
}
const UInt64 refOffset = Get64((const Byte *)(const void *)buf64 + 0x30); // must be aligned for cluster
const UInt32 refClusters = Get32((const Byte *)(const void *)buf64 + 0x38);
// UInt32 numSnapshots = Get32((const Byte *)(const void *)buf64 + 0x3C);
// UInt64 snapshotsOffset = Get64((const Byte *)(const void *)buf64 + 0x40); // must be aligned for cluster
/*
if (numSnapshots != 0)
if (numSnapshots)
return S_FALSE;
*/
if (refClusters != 0)
if (refClusters)
{
const size_t numBytes = refClusters << _clusterBits;
if (refOffset > k_CompressedSize_MAX)
return S_FALSE;
const UInt64 numBytes = (UInt64)refClusters << _clusterBits;
const UInt64 end = refOffset + numBytes;
if (end > k_CompressedSize_MAX)
return S_FALSE;
/*
CByteBuffer refs;
refs.Alloc(numBytes);
RINOK(InStream_SeekSet(stream, refOffset))
RINOK(ReadStream_FALSE(stream, refs, numBytes));
*/
const UInt64 end = refOffset + numBytes;
if (_phySize < end)
_phySize = end;
_phySize = end;
/*
for (size_t i = 0; i < numBytes; i += 2)
{
@ -436,48 +476,76 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
}
}
_isArc = true;
if (backOffset != 0)
{
_unsupported = true;
const UInt64 l1Offset = Get64((const Byte *)(const void *)buf64 + 0x28); // must be aligned for cluster ?
if (l1Offset < headerSize || l1Offset > k_CompressedSize_MAX)
return S_FALSE;
if (_phySize < headerSize)
_phySize = headerSize;
_isArc = true;
{
const UInt64 backOffset = Get64((const Byte *)(const void *)buf64 + 8);
// UInt32 backSize = Get32((const Byte *)(const void *)buf64 + 0x10);
if (backOffset)
{
_unsupported = true;
return S_FALSE;
}
}
const size_t clusterSize = (size_t)1 << _clusterBits;
UInt64 fileSize = 0;
RINOK(InStream_GetSize_SeekToBegin(stream, fileSize))
CByteBuffer table;
const size_t clusterSize = (size_t)1 << _clusterBits;
const size_t t1SizeBytes = (size_t)l1Size << 3;
{
const size_t t1SizeBytes = (size_t)l1Size << 3;
if ((t1SizeBytes >> 3) != l1Size)
const UInt64 end = l1Offset + t1SizeBytes;
if (end > k_CompressedSize_MAX)
return S_FALSE;
table.Alloc(t1SizeBytes);
RINOK(InStream_SeekSet(stream, l1Offset))
RINOK(ReadStream_FALSE(stream, table, t1SizeBytes))
{
UInt64 end = l1Offset + t1SizeBytes;
// we need to uses align end for empty qcow files
end = (end + clusterSize - 1) >> _clusterBits << _clusterBits;
if (_phySize < end)
// we need to use align end for empty qcow files
// some files has no cluster alignment padding at the end
// but has sector alignment
// end = (end + clusterSize - 1) >> _clusterBits << _clusterBits;
if (_phySize < end)
_phySize = end;
if (end > fileSize)
return S_FALSE;
if (_phySize < fileSize)
{
const UInt64 end2 = (end + 511) & ~(UInt64)511;
if (end2 == fileSize)
_phySize = end2;
}
}
CObjArray<UInt64> table64(l1Size);
{
// if ((t1SizeBytes >> 3) != l1Size) return S_FALSE;
RINOK(InStream_SeekSet(stream, l1Offset))
RINOK(ReadStream_FALSE(stream, table64, t1SizeBytes))
}
_compressedFlag = (_version <= 1) ? ((UInt64)1 << 63) : ((UInt64)1 << 62);
const UInt64 offsetMask = _compressedFlag - 1;
const size_t midSize = (size_t)1 << (_numMidBits + 3);
size_t numTables = 0;
size_t i;
UInt32 numTables = 0;
UInt32 i;
for (i = 0; i < l1Size; i++)
{
const UInt64 v = Get64((const Byte *)table + (size_t)i * 8) & offsetMask;
if (v != 0)
numTables++;
const UInt64 v = Get64(table64 + (size_t)i) & offsetMask;
if (!v)
continue;
numTables++;
const UInt64 end = v + midSize;
if (end > k_CompressedSize_MAX)
return S_FALSE;
if (_phySize < end)
_phySize = end;
if (end > fileSize)
return S_FALSE;
}
if (numTables != 0)
if (numTables)
{
const size_t size = (size_t)numTables << (_numMidBits + 3);
if (size >> (_numMidBits + 3) != numTables)
@ -485,48 +553,38 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
_table.Alloc(size);
if (!_table.IsAllocated())
return E_OUTOFMEMORY;
if (openCallback)
{
const UInt64 totalBytes = size;
RINOK(openCallback->SetTotal(NULL, &totalBytes))
}
}
_dir.SetSize(l1Size);
_dir.SetSize((unsigned)l1Size);
UInt32 curTable = 0;
if (openCallback)
{
const UInt64 totalBytes = (UInt64)numTables << (_numMidBits + 3);
RINOK(openCallback->SetTotal(NULL, &totalBytes))
}
for (i = 0; i < l1Size; i++)
{
Byte *buf2;
const size_t midSize = (size_t)1 << (_numMidBits + 3);
{
const UInt64 v = Get64((const Byte *)table + (size_t)i * 8) & offsetMask;
const UInt64 v = Get64(table64 + (size_t)i) & offsetMask;
if (v == 0)
{
_dir[i] = kEmptyDirItem;
continue;
}
_dir[i] = curTable;
const size_t tableOffset = ((size_t)curTable << (_numMidBits + 3));
const size_t tableOffset = (size_t)curTable << (_numMidBits + 3);
buf2 = (Byte *)_table + tableOffset;
curTable++;
if (openCallback && (tableOffset & 0xFFFFF) == 0)
{
const UInt64 numBytes = tableOffset;
RINOK(openCallback->SetCompleted(NULL, &numBytes))
}
RINOK(InStream_SeekSet(stream, v))
RINOK(ReadStream_FALSE(stream, buf2, midSize))
const UInt64 end = v + midSize;
if (_phySize < end)
_phySize = end;
}
for (size_t k = 0; k < midSize; k += 8)
@ -537,33 +595,30 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
UInt64 offset = v & offsetMask;
size_t dataSize = clusterSize;
if ((v & _compressedFlag) != 0)
if (v & _compressedFlag)
{
if (_version <= 1)
{
unsigned numOffsetBits = (63 - _clusterBits);
const unsigned numOffsetBits = 63 - _clusterBits;
dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9;
offset &= ((UInt64)1 << numOffsetBits) - 1;
dataSize = 0;
// offset >>= 9;
// offset <<= 9;
dataSize = 0; // why ?
// offset &= ~(((UInt64)1 << 9) - 1);
}
else
{
unsigned numOffsetBits = (62 - (_clusterBits - 8));
const unsigned numOffsetBits = 62 - (_clusterBits - 8);
dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9;
offset &= ((UInt64)1 << numOffsetBits) - 1;
offset >>= 9;
offset <<= 9;
offset &= ((UInt64)1 << numOffsetBits) - (1 << 9);
}
_needDeflate = true;
_needCompression = true;
}
else
{
UInt32 low = (UInt32)v & 511;
if (low != 0)
const UInt32 low = (UInt32)v & 511;
if (low)
{
// version 3 support zero clusters
// version_3 supports zero clusters
if (_version < 3 || low != 1)
{
_unsupported = true;
@ -574,17 +629,18 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
const UInt64 end = offset + dataSize;
if (_phySize < end)
_phySize = end;
_phySize = end;
}
}
if (curTable != numTables)
return E_FAIL;
if (_cryptMethod != 0)
if (_cryptMethod)
_unsupported = true;
if (_needDeflate && _version <= 1) // that case was not implemented
if (_needCompression && _version <= 1) // that case was not implemented
_unsupported = true;
if (_compressionType)
_unsupported = true;
Stream = stream;
@ -596,16 +652,21 @@ Z7_COM7F_IMF(CHandler::Close())
{
_table.Free();
_dir.Free();
// _cache.Free();
// _cacheCompressed.Free();
_phySize = 0;
_cacheCluster = (UInt64)(Int64)-1;
_comprPos = 0;
_comprSize = 0;
_needDeflate = false;
_needCompression = false;
_isArc = false;
_unsupported = false;
_compressionType = 0;
_incompatFlags = 0;
// CHandlerImg:
Clear_HandlerImg_Vars();
Stream.Release();
@ -617,39 +678,20 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 /* index */, ISequentialInStream **strea
{
COM_TRY_BEGIN
*stream = NULL;
if (_unsupported)
if (_unsupported || !Stream)
return S_FALSE;
if (_needDeflate)
if (_needCompression)
{
if (_version <= 1)
if (_version <= 1 || _compressionType)
return S_FALSE;
if (!_bufInStream)
{
_bufInStreamSpec = new CBufInStream;
_bufInStream = _bufInStreamSpec;
}
if (!_bufOutStream)
{
_bufOutStreamSpec = new CBufPtrSeqOutStream();
_bufOutStream = _bufOutStreamSpec;
}
if (!_deflateDecoder)
{
_deflateDecoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder();
_deflateDecoder = _deflateDecoderSpec;
_deflateDecoderSpec->Set_NeedFinishInput(true);
}
_bufInStream.Create_if_Empty();
_bufOutStream.Create_if_Empty();
_deflateDecoder.Create_if_Empty();
_deflateDecoder->Set_NeedFinishInput(true);
const size_t clusterSize = (size_t)1 << _clusterBits;
_cache.AllocAtLeast(clusterSize);
_cacheCompressed.AllocAtLeast(clusterSize * 2);
}
CMyComPtr<ISequentialInStream> streamTemp = this;
RINOK(InitAndSeek())
*stream = streamTemp.Detach();

View file

@ -658,6 +658,9 @@ HRESULT CInArchive::ReadBlockHeader(CHeader &h)
RINOK(ReadStream_Check(_buf, AES_BLOCK_SIZE * 2))
memcpy(m_CryptoDecoder->_iv, _buf, AES_BLOCK_SIZE);
RINOK(m_CryptoDecoder->Init())
// we call RAR5_AES_Filter with:
// data_ptr == aligned_ptr + 16
// data_size == 16
if (m_CryptoDecoder->Filter(_buf + AES_BLOCK_SIZE, AES_BLOCK_SIZE) != AES_BLOCK_SIZE)
return E_FAIL;
memcpy(buf, _buf + AES_BLOCK_SIZE, AES_BLOCK_SIZE);
@ -689,10 +692,14 @@ HRESULT CInArchive::ReadBlockHeader(CHeader &h)
return E_OUTOFMEMORY;
memcpy(_buf, buf, filled);
const size_t rem = size - filled;
// if (m_CryptoMode), we add AES_BLOCK_SIZE here, because _iv is not included to size.
AddToSeekValue(size + (m_CryptoMode ? AES_BLOCK_SIZE : 0));
RINOK(ReadStream_Check(_buf + filled, rem))
if (m_CryptoMode)
{
// we call RAR5_AES_Filter with:
// data_ptr == aligned_ptr + 16
// (rem) can be big
if (m_CryptoDecoder->Filter(_buf + filled, (UInt32)rem) != rem)
return E_FAIL;
#if 1
@ -1065,7 +1072,8 @@ HRESULT CUnpacker::Create(DECL_EXTERNAL_CODECS_LOC_VARS
CMyComPtr<ICompressSetDecoderProperties2> csdp;
RINOK(lzCoder.QueryInterface(IID_ICompressSetDecoderProperties2, &csdp))
if (!csdp)
return E_NOTIMPL;
const unsigned ver = item.Get_AlgoVersion_HuffRev();
if (ver > 1)
return E_NOTIMPL;
@ -1456,7 +1464,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
}
if (arcInfo->Locator.Is_Recovery())
{
s += "Recovery:";
s.Add_OptSpaced("Recovery:");
s.Add_UInt64(arcInfo->Locator.Recovery);
}
}
@ -3343,9 +3351,9 @@ Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
}
else if (name.IsPrefixedBy_Ascii_NoCase("memx"))
{
UInt64 memAvail;
size_t memAvail;
if (!NWindows::NSystem::GetRamSize(memAvail))
memAvail = (UInt64)(sizeof(size_t)) << 28;
memAvail = (size_t)sizeof(size_t) << 28;
UInt64 v;
if (!ParseSizeString(name.Ptr(4), prop, memAvail, v))
return E_INVALIDARG;

View file

@ -1579,6 +1579,8 @@ HRESULT CHandler::OpenCapsule(IInStream *stream)
|| _h.CapsuleImageSize < _h.HeaderSize
|| _h.OffsetToCapsuleBody < _h.HeaderSize
|| _h.OffsetToCapsuleBody > _h.CapsuleImageSize
|| _h.CapsuleImageSize > (1u << 30) // to reduce false detection
|| _h.HeaderSize > (1u << 28) // to reduce false detection
)
return S_FALSE;
_phySize = _h.CapsuleImageSize;
@ -1587,7 +1589,7 @@ HRESULT CHandler::OpenCapsule(IInStream *stream)
_h.OffsetToSplitInformation != 0 )
return E_NOTIMPL;
unsigned bufIndex = AddBuf(_h.CapsuleImageSize);
const unsigned bufIndex = AddBuf(_h.CapsuleImageSize);
CByteBuffer &buf0 = _bufs[bufIndex];
memcpy(buf0, buf, kHeaderSize);
ReadStream_FALSE(stream, buf0 + kHeaderSize, _h.CapsuleImageSize - kHeaderSize);

View file

@ -3,6 +3,7 @@
#include "StdAfx.h"
#include "../../../C/Sha256.h"
#include "../../../C/Sha512.h"
#include "../../../C/CpuArch.h"
#include "../../Common/ComTry.h"
@ -41,22 +42,33 @@ Z7_CLASS_IMP_NOQIB_1(
CInStreamWithSha256
, ISequentialInStream
)
bool _sha512Mode;
CMyComPtr<ISequentialInStream> _stream;
CAlignedBuffer1 _sha;
CAlignedBuffer1 _sha256;
CAlignedBuffer1 _sha512;
UInt64 _size;
CSha256 *Sha() { return (CSha256 *)(void *)(Byte *)_sha; }
CSha256 *Sha256() { return (CSha256 *)(void *)(Byte *)_sha256; }
CSha512 *Sha512() { return (CSha512 *)(void *)(Byte *)_sha512; }
public:
CInStreamWithSha256(): _sha(sizeof(CSha256)) {}
CInStreamWithSha256():
_sha256(sizeof(CSha256)),
_sha512(sizeof(CSha512))
{}
void SetStream(ISequentialInStream *stream) { _stream = stream; }
void Init()
void Init(bool sha512Mode)
{
_sha512Mode = sha512Mode;
_size = 0;
Sha256_Init(Sha());
if (sha512Mode)
Sha512_Init(Sha512(), SHA512_DIGEST_SIZE);
else
Sha256_Init(Sha256());
}
void ReleaseStream() { _stream.Release(); }
UInt64 GetSize() const { return _size; }
void Final(Byte *digest) { Sha256_Final(Sha(), digest); }
void Final256(Byte *digest) { Sha256_Final(Sha256(), digest); }
void Final512(Byte *digest) { Sha512_Final(Sha512(), digest, SHA512_DIGEST_SIZE); }
};
Z7_COM7F_IMF(CInStreamWithSha256::Read(void *data, UInt32 size, UInt32 *processedSize))
@ -64,7 +76,10 @@ Z7_COM7F_IMF(CInStreamWithSha256::Read(void *data, UInt32 size, UInt32 *processe
UInt32 realProcessedSize;
const HRESULT result = _stream->Read(data, size, &realProcessedSize);
_size += realProcessedSize;
Sha256_Update(Sha(), (const Byte *)data, realProcessedSize);
if (_sha512Mode)
Sha512_Update(Sha512(), (const Byte *)data, realProcessedSize);
else
Sha256_Update(Sha256(), (const Byte *)data, realProcessedSize);
if (processedSize)
*processedSize = realProcessedSize;
return result;
@ -75,25 +90,33 @@ Z7_CLASS_IMP_NOQIB_1(
COutStreamWithSha256
, ISequentialOutStream
)
// bool _calculate;
bool _sha512Mode;
CMyComPtr<ISequentialOutStream> _stream;
CAlignedBuffer1 _sha;
CAlignedBuffer1 _sha256;
CAlignedBuffer1 _sha512;
UInt64 _size;
CSha256 *Sha() { return (CSha256 *)(void *)(Byte *)_sha; }
CSha256 *Sha256() { return (CSha256 *)(void *)(Byte *)_sha256; }
CSha512 *Sha512() { return (CSha512 *)(void *)(Byte *)_sha512; }
public:
COutStreamWithSha256(): _sha(sizeof(CSha256)) {}
COutStreamWithSha256():
_sha256(sizeof(CSha256)),
_sha512(sizeof(CSha512))
{}
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
void ReleaseStream() { _stream.Release(); }
void Init(/* bool calculate = true */ )
void Init(bool sha512Mode)
{
// _calculate = calculate;
_sha512Mode = sha512Mode;
_size = 0;
Sha256_Init(Sha());
if (sha512Mode)
Sha512_Init(Sha512(), SHA512_DIGEST_SIZE);
else
Sha256_Init(Sha256());
}
void InitSha256() { Sha256_Init(Sha()); }
UInt64 GetSize() const { return _size; }
void Final(Byte *digest) { Sha256_Final(Sha(), digest); }
void Final256(Byte *digest) { Sha256_Final(Sha256(), digest); }
void Final512(Byte *digest) { Sha512_Final(Sha512(), digest, SHA512_DIGEST_SIZE); }
};
Z7_COM7F_IMF(COutStreamWithSha256::Write(const void *data, UInt32 size, UInt32 *processedSize))
@ -102,7 +125,10 @@ Z7_COM7F_IMF(COutStreamWithSha256::Write(const void *data, UInt32 size, UInt32 *
if (_stream)
result = _stream->Write(data, size, &size);
// if (_calculate)
Sha256_Update(Sha(), (const Byte *)data, size);
if (_sha512Mode)
Sha512_Update(Sha512(), (const Byte *)data, size);
else
Sha256_Update(Sha256(), (const Byte *)data, size);
_size += size;
if (processedSize)
*processedSize = size;
@ -521,10 +547,11 @@ void CInStreamWithHash::SetStreamAndInit(ISequentialInStream *stream, int algo)
inStreamSha1->Init();
stream = inStreamSha1;
}
else if (algo == XAR_CKSUM_SHA256)
else if (algo == XAR_CKSUM_SHA256
|| algo == XAR_CKSUM_SHA512)
{
inStreamSha256->SetStream(stream);
inStreamSha256->Init();
inStreamSha256->Init(algo == XAR_CKSUM_SHA512);
stream = inStreamSha256;
}
inStreamLim->SetStream(stream);
@ -542,7 +569,14 @@ bool CInStreamWithHash::CheckHash(int algo, const Byte *digest_from_arc) const
else if (algo == XAR_CKSUM_SHA256)
{
Byte digest[SHA256_DIGEST_SIZE];
inStreamSha256->Final(digest);
inStreamSha256->Final256(digest);
if (memcmp(digest, digest_from_arc, sizeof(digest)) != 0)
return false;
}
else if (algo == XAR_CKSUM_SHA512)
{
Byte digest[SHA512_DIGEST_SIZE];
inStreamSha256->Final512(digest);
if (memcmp(digest, digest_from_arc, sizeof(digest)) != 0)
return false;
}
@ -1151,11 +1185,12 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
outStreamSha1->SetStream(realOutStream);
outStreamSha1->Init();
}
else if (checksum_method == XAR_CKSUM_SHA256)
else if (checksum_method == XAR_CKSUM_SHA256
|| checksum_method == XAR_CKSUM_SHA512)
{
outStreamLim->SetStream(outStreamSha256);
outStreamSha256->SetStream(realOutStream);
outStreamSha256->Init();
outStreamSha256->Init(checksum_method == XAR_CKSUM_SHA512);
}
else
outStreamLim->SetStream(realOutStream);
@ -1209,8 +1244,15 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
else if (checksum_method == XAR_CKSUM_SHA256)
{
Byte digest[SHA256_DIGEST_SIZE];
outStreamSha256->Final(digest);
if (memcmp(digest, item.extracted_checksum.Data, SHA256_DIGEST_SIZE) != 0)
outStreamSha256->Final256(digest);
if (memcmp(digest, item.extracted_checksum.Data, sizeof(digest)) != 0)
opRes = NExtract::NOperationResult::kCRCError;
}
else if (checksum_method == XAR_CKSUM_SHA512)
{
Byte digest[SHA512_DIGEST_SIZE];
outStreamSha256->Final512(digest);
if (memcmp(digest, item.extracted_checksum.Data, sizeof(digest)) != 0)
opRes = NExtract::NOperationResult::kCRCError;
}
if (opRes == NExtract::NOperationResult::kOK)

View file

@ -967,9 +967,9 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
|| _maxBlocksSize != (size_t)_maxBlocksSize)
return S_FALSE;
UInt64 memSize;
size_t memSize;
if (!NSystem::GetRamSize(memSize))
memSize = (UInt64)(sizeof(size_t)) << 28;
memSize = (size_t)sizeof(size_t) << 28;
{
if (_maxBlocksSize > memSize / 4)
return S_FALSE;

View file

@ -1755,16 +1755,17 @@ HRESULT CCacheOutStream::FlushFromCache(size_t size)
PRF(printf("\n-- CCacheOutStream::FlushFromCache %u\n", (unsigned)size));
if (_hres != S_OK)
return _hres;
if (size == 0 || _cachedSize == 0)
if (size > _cachedSize)
size = _cachedSize;
// (size <= _cachedSize)
if (size == 0)
return S_OK;
RINOK(SeekPhy(_cachedPos))
for (;;)
{
// (_phyPos == _cachedPos)
const size_t pos = (size_t)_cachedPos & kCacheMask;
size_t cur = kCacheSize - pos;
cur = MyMin(cur, _cachedSize);
cur = MyMin(cur, size);
const size_t cur = MyMin(kCacheSize - pos, size);
_hres = SetRestriction_ForWrite(cur);
RINOK(_hres)
PRF(printf("\n-- CCacheOutStream::WriteFromCache _phyPos = 0x%x, size = %d\n", (unsigned)_phyPos, (unsigned)cur));
@ -1776,7 +1777,7 @@ HRESULT CCacheOutStream::FlushFromCache(size_t size)
_cachedPos += cur;
_cachedSize -= cur;
size -= cur;
if (size == 0 || _cachedSize == 0)
if (size == 0)
return S_OK;
}
}
@ -1964,7 +1965,11 @@ Z7_COM7F_IMF(CCacheOutStream::SetSize(UInt64 newSize))
// so we reduce cache
_cachedSize = (size_t)offset;
if (_phySize <= newSize)
return S_OK; // _phySize will be restored later after cache flush
{
// _phySize will be restored later after cache flush
_virtSize = newSize;
return S_OK;
}
// (_phySize > newSize)
// so we must reduce phyStream size to (newSize) or to (_cachedPos)
// newPhySize = _cachedPos; // optional reduce to _cachedPos

View file

@ -4,6 +4,7 @@ COMMON_OBJS = \
$O\DynLimBuf.obj \
$O\IntToString.obj \
$O\LzFindPrepare.obj \
$O\Md5Reg.obj \
$O\MyMap.obj \
$O\MyString.obj \
$O\MyVector.obj \
@ -11,6 +12,9 @@ COMMON_OBJS = \
$O\NewHandler.obj \
$O\Sha1Reg.obj \
$O\Sha256Reg.obj \
$O\Sha3Reg.obj \
$O\Sha512Reg.obj \
$O\Sha512Prepare.obj \
$O\StringConvert.obj \
$O\StringToInt.obj \
$O\UTFConvert.obj \
@ -274,6 +278,7 @@ C_OBJS = \
$O\Lzma2Enc.obj \
$O\LzmaDec.obj \
$O\LzmaEnc.obj \
$O\Md5.obj \
$O\MtCoder.obj \
$O\MtDec.obj \
$O\Ppmd7.obj \
@ -283,6 +288,9 @@ C_OBJS = \
$O\Ppmd8.obj \
$O\Ppmd8Dec.obj \
$O\Ppmd8Enc.obj \
$O\Sha3.obj \
$O\Sha512.obj \
$O\Sha512Opt.obj \
$O\Sort.obj \
$O\SwapBytes.obj \
$O\Threads.obj \

View file

@ -45,6 +45,7 @@ COMMON_OBJS = \
$O/DynLimBuf.o \
$O/IntToString.o \
$O/LzFindPrepare.o \
$O/Md5Reg.o \
$O/MyMap.o \
$O/MyString.o \
$O/MyVector.o \
@ -54,6 +55,9 @@ COMMON_OBJS = \
$O/Sha1Reg.o \
$O/Sha256Prepare.o \
$O/Sha256Reg.o \
$O/Sha3Reg.o \
$O/Sha512Prepare.o \
$O/Sha512Reg.o \
$O/StringConvert.o \
$O/StringToInt.o \
$O/UTFConvert.o \
@ -337,6 +341,7 @@ C_OBJS = \
$O/Lzma2Enc.o \
$O/LzmaDec.o \
$O/LzmaEnc.o \
$O/Md5.o \
$O/MtCoder.o \
$O/MtDec.o \
$O/Ppmd7.o \
@ -350,6 +355,9 @@ C_OBJS = \
$O/Sha1Opt.o \
$O/Sha256.o \
$O/Sha256Opt.o \
$O/Sha3.o \
$O/Sha512.o \
$O/Sha512Opt.o \
$O/Sort.o \
$O/SwapBytes.o \
$O/Xxh64.o \

View file

@ -287,6 +287,10 @@ SOURCE=..\..\..\Common\LzFindPrepare.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Md5Reg.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\MyBuffer.h
# End Source File
# Begin Source File
@ -383,6 +387,18 @@ SOURCE=..\..\..\Common\Sha256Reg.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Sha3Reg.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Sha512Prepare.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Sha512Reg.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\StringConvert.cpp
# End Source File
# Begin Source File
@ -2029,6 +2045,26 @@ SOURCE=..\..\..\..\C\LzmaEnc.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Md5.c
!IF "$(CFG)" == "7z - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Md5.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\MtCoder.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
@ -2230,6 +2266,62 @@ SOURCE=..\..\..\..\C\Sha256.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Sha3.c
!IF "$(CFG)" == "7z - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Sha3.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Sha512.c
!IF "$(CFG)" == "7z - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Sha512.h
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Sha512Opt.c
!IF "$(CFG)" == "7z - Win32 Release"
# ADD CPP /O2
# SUBTRACT CPP /YX /Yc /Yu
!ELSEIF "$(CFG)" == "7z - Win32 Debug"
# SUBTRACT CPP /YX /Yc /Yu
!ENDIF
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Sort.c
!IF "$(CFG)" == "7z - Win32 Release"

View file

@ -59,13 +59,13 @@ static const char * const kHelpString =
" b : Benchmark\n"
"<switches>\n"
" -a{N} : set compression mode : [0, 1] : default = 1 (max)\n"
" -d{N} : set dictionary size : [12, 30] : default = 24 (16 MiB)\n"
" -d{N} : set dictionary size : [12, 31] : default = 24 (16 MiB)\n"
" -fb{N} : set number of fast bytes : [5, 273] : default = 128\n"
" -mc{N} : set number of cycles for match finder\n"
" -lc{N} : set number of literal context bits : [0, 8] : default = 3\n"
" -lp{N} : set number of literal pos bits : [0, 4] : default = 0\n"
" -pb{N} : set number of pos bits : [0, 4] : default = 2\n"
" -mf{M} : set match finder: [hc4, bt2, bt3, bt4] : default = bt4\n"
" -mf{M} : set match finder: [hc4, hc5, bt2, bt3, bt4, bt5] : default = bt4\n"
" -mt{N} : set number of CPU threads\n"
" -eos : write end of stream marker\n"
" -si : read data from stdin\n"
@ -372,8 +372,8 @@ static int main2(int numArgs, const char *args[])
return 0;
}
bool stdInMode = parser[NKey::kStdIn].ThereIs;
bool stdOutMode = parser[NKey::kStdOut].ThereIs;
const bool stdInMode = parser[NKey::kStdIn].ThereIs;
const bool stdOutMode = parser[NKey::kStdOut].ThereIs;
if (!stdOutMode)
PrintTitle();
@ -394,7 +394,16 @@ static int main2(int numArgs, const char *args[])
UInt32 dictLog;
const UString &s = parser[NKey::kDict].PostStrings[0];
dictLog = GetNumber(s);
dict = 1 << dictLog;
if (dictLog >= 32)
throw "unsupported dictionary size";
// we only want to use dictionary sizes that are powers of 2,
// because 7-zip only recognizes such dictionary sizes in the lzma header.#if 0
#if 0
if (dictLog == 32)
dict = (UInt32)3840 << 20;
else
#endif
dict = (UInt32)1 << dictLog;
dictDefined = true;
AddProp(props2, "d", s);
}
@ -522,7 +531,7 @@ static int main2(int numArgs, const char *args[])
if (encodeMode && !dictDefined)
{
dict = 1 << kDictSizeLog;
dict = (UInt32)1 << kDictSizeLog;
if (fileSizeDefined)
{
unsigned i;

View file

@ -422,7 +422,7 @@ int Main2(
{
CExtractCallbackConsole *ecs = new CExtractCallbackConsole;
CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;
ecs->Init(g_StdStream, &g_StdErr, g_StdStream);
ecs->Init(g_StdStream, &g_StdErr, g_StdStream, false);
#ifndef Z7_NO_CRYPTO
ecs->PasswordIsDefined = passwordEnabled;

View file

@ -35,7 +35,7 @@ void RegisterCodec(const CCodecInfo *codecInfo) throw()
g_Codecs[g_NumCodecs++] = codecInfo;
}
static const unsigned kNumHashersMax = 16;
static const unsigned kNumHashersMax = 32;
extern
unsigned g_NumHashers;
unsigned g_NumHashers = 0;

View file

@ -125,7 +125,7 @@ public:
UInt32 Get_Lzma_Algo() const
{
int i = FindProp(NCoderPropID::kAlgorithm);
const int i = FindProp(NCoderPropID::kAlgorithm);
if (i >= 0)
{
const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value;
@ -141,11 +141,11 @@ public:
if (Get_DicSize(v))
return v;
const unsigned level = GetLevel();
const UInt32 dictSize =
( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) :
( level <= 6 ? ((UInt32)1 << (level + 19)) :
( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26)
)));
const UInt32 dictSize = level <= 4 ?
(UInt32)1 << (level * 2 + 16) :
level <= sizeof(size_t) / 2 + 4 ?
(UInt32)1 << (level + 20) :
(UInt32)1 << (sizeof(size_t) / 2 + 24);
return dictSize;
}

View file

@ -196,29 +196,17 @@ static void x86_Filter(Byte *data, UInt32 size, Int32 *history)
const Byte b = p[0];
if (b == 0x48)
if ((b & 0x80) == 0) // REX (0x48 or 0x4c)
{
if (p[1] == 0x8B)
const unsigned b2 = p[2] - 0x5; // [RIP + disp32]
if (b2 & 0x7)
continue;
if (p[1] != 0x8d) // LEA
{
if ((p[2] & 0xF7) != 0x5)
if (p[1] != 0x8b || b != 0x48 || (b2 & 0xf7))
continue;
// MOV RAX / RCX, [RIP + disp32]
}
else if (p[1] == 0x8D) // LEA
{
if ((p[2] & 0x7) != 0x5)
continue;
// LEA R**, []
}
else
continue;
codeLen = 3;
}
else if (b == 0x4C)
{
if (p[1] != 0x8D || (p[2] & 0x7) != 0x5)
continue;
// LEA R*, []
codeLen = 3;
}
else if (b == 0xE8)

View file

@ -8,16 +8,17 @@
#include "../../Windows/Synchronization.h"
#endif
#include "Rar5Aes.h"
#include "HmacSha256.h"
#include "Rar5Aes.h"
#define MY_ALIGN_FOR_SHA256 MY_ALIGN(16)
namespace NCrypto {
namespace NRar5 {
static const unsigned kNumIterationsLog_Max = 24;
static const unsigned kPswCheckCsumSize = 4;
static const unsigned kCheckSize = kPswCheckSize + kPswCheckCsumSize;
static const unsigned kPswCheckCsumSize32 = 1;
static const unsigned kCheckSize32 = kPswCheckSize32 + kPswCheckCsumSize32;
CKey::CKey():
_needCalc(true),
@ -27,15 +28,29 @@ CKey::CKey():
_salt[i] = 0;
}
CKey::~CKey()
{
Wipe();
}
void CKey::Wipe()
{
_password.Wipe();
Z7_memset_0_ARRAY(_salt);
// Z7_memset_0_ARRAY(_key32);
// Z7_memset_0_ARRAY(_check_Calced32);
// Z7_memset_0_ARRAY(_hashKey32);
CKeyBase::Wipe();
}
CDecoder::CDecoder(): CAesCbcDecoder(kAesKeySize) {}
static unsigned ReadVarInt(const Byte *p, unsigned maxSize, UInt64 *val)
{
*val = 0;
for (unsigned i = 0; i < maxSize && i < 10;)
{
Byte b = p[i];
const Byte b = p[i];
*val |= (UInt64)(b & 0x7F) << (7 * i);
i++;
if ((b & 0x80) == 0)
@ -64,7 +79,7 @@ HRESULT CDecoder::SetDecoderProps(const Byte *p, unsigned size, bool includeIV,
size -= num;
bool isCheck = IsThereCheck();
if (size != 1 + kSaltSize + (includeIV ? AES_BLOCK_SIZE : 0) + (unsigned)(isCheck ? kCheckSize : 0))
if (size != 1 + kSaltSize + (includeIV ? AES_BLOCK_SIZE : 0) + (unsigned)(isCheck ? kCheckSize32 * 4 : 0))
return E_NOTIMPL;
if (_numIterationsLog != p[0])
@ -93,19 +108,21 @@ HRESULT CDecoder::SetDecoderProps(const Byte *p, unsigned size, bool includeIV,
if (isCheck)
{
memcpy(_check, p, kPswCheckSize);
memcpy(_check32, p, sizeof(_check32));
MY_ALIGN_FOR_SHA256
CSha256 sha;
MY_ALIGN_FOR_SHA256
Byte digest[SHA256_DIGEST_SIZE];
Sha256_Init(&sha);
Sha256_Update(&sha, _check, kPswCheckSize);
Sha256_Update(&sha, (const Byte *)_check32, sizeof(_check32));
Sha256_Final(&sha, digest);
_canCheck = (memcmp(digest, p + kPswCheckSize, kPswCheckCsumSize) == 0);
_canCheck = (memcmp(digest, p + sizeof(_check32), kPswCheckCsumSize32 * 4) == 0);
if (_canCheck && isService)
{
// There was bug in RAR 5.21- : PswCheck field in service records ("QO") contained zeros.
// so we disable password checking for such bad records.
_canCheck = false;
for (unsigned i = 0; i < kPswCheckSize; i++)
for (unsigned i = 0; i < kPswCheckSize32 * 4; i++)
if (p[i] != 0)
{
_canCheck = true;
@ -132,7 +149,7 @@ void CDecoder::SetPassword(const Byte *data, size_t size)
Z7_COM7F_IMF(CDecoder::Init())
{
CalcKey_and_CheckPassword();
RINOK(SetKey(_key, kAesKeySize))
RINOK(SetKey((const Byte *)_key32, kAesKeySize))
RINOK(SetInitVector(_iv, AES_BLOCK_SIZE))
return CAesCoder::Init();
}
@ -140,27 +157,27 @@ Z7_COM7F_IMF(CDecoder::Init())
UInt32 CDecoder::Hmac_Convert_Crc32(UInt32 crc) const
{
MY_ALIGN (16)
MY_ALIGN_FOR_SHA256
NSha256::CHmac ctx;
ctx.SetKey(_hashKey, NSha256::kDigestSize);
ctx.SetKey((const Byte *)_hashKey32, NSha256::kDigestSize);
UInt32 v;
SetUi32(&v, crc)
SetUi32a(&v, crc)
ctx.Update((const Byte *)&v, 4);
MY_ALIGN (16)
MY_ALIGN_FOR_SHA256
UInt32 h[SHA256_NUM_DIGEST_WORDS];
ctx.Final((Byte *)h);
crc = 0;
for (unsigned i = 0; i < SHA256_NUM_DIGEST_WORDS; i++)
crc ^= (UInt32)GetUi32(h + i);
crc ^= (UInt32)GetUi32a(h + i);
return crc;
}
void CDecoder::Hmac_Convert_32Bytes(Byte *data) const
{
MY_ALIGN (16)
MY_ALIGN_FOR_SHA256
NSha256::CHmac ctx;
ctx.SetKey(_hashKey, NSha256::kDigestSize);
ctx.SetKey((const Byte *)_hashKey32, NSha256::kDigestSize);
ctx.Update(data, NSha256::kDigestSize);
ctx.Final(data);
}
@ -190,30 +207,31 @@ bool CDecoder::CalcKey_and_CheckPassword()
if (_needCalc)
{
Byte pswCheck[SHA256_DIGEST_SIZE];
MY_ALIGN_FOR_SHA256
UInt32 pswCheck[SHA256_NUM_DIGEST_WORDS];
{
// Pbkdf HMAC-SHA-256
MY_ALIGN (16)
MY_ALIGN_FOR_SHA256
NSha256::CHmac baseCtx;
baseCtx.SetKey(_password, _password.Size());
NSha256::CHmac ctx = baseCtx;
MY_ALIGN_FOR_SHA256
NSha256::CHmac ctx;
ctx = baseCtx;
ctx.Update(_salt, sizeof(_salt));
MY_ALIGN (16)
Byte u[NSha256::kDigestSize];
MY_ALIGN (16)
Byte key[NSha256::kDigestSize];
MY_ALIGN_FOR_SHA256
UInt32 u[SHA256_NUM_DIGEST_WORDS];
MY_ALIGN_FOR_SHA256
UInt32 key[SHA256_NUM_DIGEST_WORDS];
u[0] = 0;
u[1] = 0;
u[2] = 0;
u[3] = 1;
// u[0] = 0;
// u[1] = 0;
// u[2] = 0;
// u[3] = 1;
SetUi32a(u, 0x1000000)
ctx.Update(u, 4);
ctx.Final(u);
ctx.Update((const Byte *)(const void *)u, 4);
ctx.Final((Byte *)(void *)u);
memcpy(key, u, NSha256::kDigestSize);
@ -221,35 +239,24 @@ bool CDecoder::CalcKey_and_CheckPassword()
for (unsigned i = 0; i < 3; i++)
{
UInt32 j = numIterations;
for (; j != 0; j--)
for (; numIterations != 0; numIterations--)
{
ctx = baseCtx;
ctx.Update(u, NSha256::kDigestSize);
ctx.Final(u);
for (unsigned s = 0; s < NSha256::kDigestSize; s++)
ctx.Update((const Byte *)(const void *)u, NSha256::kDigestSize);
ctx.Final((Byte *)(void *)u);
for (unsigned s = 0; s < Z7_ARRAY_SIZE(u); s++)
key[s] ^= u[s];
}
// RAR uses additional iterations for additional keys
memcpy((i == 0 ? _key : (i == 1 ? _hashKey : pswCheck)), key, NSha256::kDigestSize);
memcpy(i == 0 ? _key32 : i == 1 ? _hashKey32 : pswCheck,
key, NSha256::kDigestSize);
numIterations = 16;
}
}
{
unsigned i;
for (i = 0; i < kPswCheckSize; i++)
_check_Calced[i] = pswCheck[i];
for (i = kPswCheckSize; i < SHA256_DIGEST_SIZE; i++)
_check_Calced[i & (kPswCheckSize - 1)] ^= pswCheck[i];
}
_check_Calced32[0] = pswCheck[0] ^ pswCheck[2] ^ pswCheck[4] ^ pswCheck[6];
_check_Calced32[1] = pswCheck[1] ^ pswCheck[3] ^ pswCheck[5] ^ pswCheck[7];
_needCalc = false;
{
MT_LOCK
g_Key = *this;
@ -258,7 +265,7 @@ bool CDecoder::CalcKey_and_CheckPassword()
}
if (IsThereCheck() && _canCheck)
return (memcmp(_check_Calced, _check, kPswCheckSize) == 0);
return memcmp(_check_Calced32, _check32, sizeof(_check32)) == 0;
return true;
}

View file

@ -13,7 +13,7 @@ namespace NCrypto {
namespace NRar5 {
const unsigned kSaltSize = 16;
const unsigned kPswCheckSize = 8;
const unsigned kPswCheckSize32 = 2;
const unsigned kAesKeySize = 32;
namespace NCryptoFlags
@ -22,48 +22,47 @@ namespace NCryptoFlags
const unsigned kUseMAC = 1 << 1;
}
struct CKey
struct CKeyBase
{
bool _needCalc;
unsigned _numIterationsLog;
Byte _salt[kSaltSize];
CByteBuffer _password;
Byte _key[kAesKeySize];
Byte _check_Calced[kPswCheckSize];
Byte _hashKey[SHA256_DIGEST_SIZE];
void CopyCalcedKeysFrom(const CKey &k)
{
memcpy(_key, k._key, sizeof(_key));
memcpy(_check_Calced, k._check_Calced, sizeof(_check_Calced));
memcpy(_hashKey, k._hashKey, sizeof(_hashKey));
}
bool IsKeyEqualTo(const CKey &key)
{
return (_numIterationsLog == key._numIterationsLog
&& memcmp(_salt, key._salt, sizeof(_salt)) == 0
&& _password == key._password);
}
CKey();
protected:
UInt32 _key32[kAesKeySize / 4];
UInt32 _hashKey32[SHA256_NUM_DIGEST_WORDS];
UInt32 _check_Calced32[kPswCheckSize32];
void Wipe()
{
_password.Wipe();
Z7_memset_0_ARRAY(_salt);
Z7_memset_0_ARRAY(_key);
Z7_memset_0_ARRAY(_check_Calced);
Z7_memset_0_ARRAY(_hashKey);
memset(this, 0, sizeof(*this));
}
void CopyCalcedKeysFrom(const CKeyBase &k)
{
*this = k;
}
};
struct CKey: public CKeyBase
{
CByteBuffer _password;
bool _needCalc;
unsigned _numIterationsLog;
Byte _salt[kSaltSize];
bool IsKeyEqualTo(const CKey &key)
{
return _numIterationsLog == key._numIterationsLog
&& memcmp(_salt, key._salt, sizeof(_salt)) == 0
&& _password == key._password;
}
CKey();
~CKey();
void Wipe();
#ifdef Z7_CPP_IS_SUPPORTED_default
// CKey(const CKey &) = default;
CKey& operator =(const CKey &) = default;
#endif
~CKey() { Wipe(); }
};
@ -71,11 +70,11 @@ class CDecoder Z7_final:
public CAesCbcDecoder,
public CKey
{
Byte _check[kPswCheckSize];
UInt32 _check32[kPswCheckSize32];
bool _canCheck;
UInt64 Flags;
bool IsThereCheck() const { return ((Flags & NCryptoFlags::kPswCheck) != 0); }
bool IsThereCheck() const { return (Flags & NCryptoFlags::kPswCheck) != 0; }
public:
Byte _iv[AES_BLOCK_SIZE];

View file

@ -111,7 +111,8 @@ static void UpdatePswDataSha1(Byte *data)
for (i = 16; i < 80; i++)
{
WW(i) = rotlFixed(WW((i)-3) ^ WW((i)-8) ^ WW((i)-14) ^ WW((i)-16), 1);
const UInt32 t = WW((i)-3) ^ WW((i)-8) ^ WW((i)-14) ^ WW((i)-16);
WW(i) = rotlFixed(t, 1);
}
for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++)
@ -128,6 +129,7 @@ void CDecoder::CalcKey()
const unsigned kSaltSize = 8;
MY_ALIGN (16)
Byte buf[kPasswordLen_Bytes_MAX + kSaltSize];
if (_password.Size() != 0)
@ -148,7 +150,7 @@ void CDecoder::CalcKey()
MY_ALIGN (16)
Byte digest[NSha1::kDigestSize];
// rar reverts hash for sha.
const UInt32 kNumRounds = ((UInt32)1 << 18);
const UInt32 kNumRounds = (UInt32)1 << 18;
UInt32 pos = 0;
UInt32 i;
for (i = 0; i < kNumRounds; i++)
@ -171,8 +173,14 @@ void CDecoder::CalcKey()
}
}
pos += (UInt32)rawSize;
#if 1
UInt32 pswNum;
SetUi32a(&pswNum, i)
sha.Update((const Byte *)&pswNum, 3);
#else
Byte pswNum[3] = { (Byte)i, (Byte)(i >> 8), (Byte)(i >> 16) };
sha.Update(pswNum, 3);
#endif
pos += 3;
if (i % (kNumRounds / 16) == 0)
{

View file

@ -24,30 +24,31 @@ static const UInt16 kAES128 = 0x660E;
if (method != AES && method != 3DES), probably we need another code.
*/
static void DeriveKey2(const Byte *digest, Byte c, Byte *dest)
static void DeriveKey2(const UInt32 *digest32, Byte c, UInt32 *dest32)
{
const unsigned kBufSize = 64;
MY_ALIGN (16)
Byte buf[64];
memset(buf, c, 64);
for (unsigned i = 0; i < NSha1::kDigestSize; i++)
buf[i] ^= digest[i];
UInt32 buf32[kBufSize / 4];
memset(buf32, c, kBufSize);
for (unsigned i = 0; i < NSha1::kNumDigestWords; i++)
buf32[i] ^= digest32[i];
MY_ALIGN (16)
NSha1::CContext sha;
sha.Init();
sha.Update(buf, 64);
sha.Final(dest);
sha.Update((const Byte *)buf32, kBufSize);
sha.Final((Byte *)dest32);
}
static void DeriveKey(NSha1::CContext &sha, Byte *key)
{
MY_ALIGN (16)
Byte digest[NSha1::kDigestSize];
sha.Final(digest);
UInt32 digest32[NSha1::kNumDigestWords];
sha.Final((Byte *)digest32);
MY_ALIGN (16)
Byte temp[NSha1::kDigestSize * 2];
DeriveKey2(digest, 0x36, temp);
DeriveKey2(digest, 0x5C, temp + NSha1::kDigestSize);
memcpy(key, temp, 32);
UInt32 temp32[NSha1::kNumDigestWords * 2];
DeriveKey2(digest32, 0x36, temp32);
DeriveKey2(digest32, 0x5C, temp32 + NSha1::kNumDigestWords);
memcpy(key, temp32, 32);
}
void CKeyInfo::SetPassword(const Byte *data, UInt32 size)
@ -122,24 +123,24 @@ HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK)
passwOK = false;
if (_remSize < 16)
return E_NOTIMPL;
Byte *p = _bufAligned;
const unsigned format = GetUi16(p);
Byte * const p = _bufAligned;
const unsigned format = GetUi16a(p);
if (format != 3)
return E_NOTIMPL;
unsigned algId = GetUi16(p + 2);
unsigned algId = GetUi16a(p + 2);
if (algId < kAES128)
return E_NOTIMPL;
algId -= kAES128;
if (algId > 2)
return E_NOTIMPL;
const unsigned bitLen = GetUi16(p + 4);
const unsigned flags = GetUi16(p + 6);
const unsigned bitLen = GetUi16a(p + 4);
const unsigned flags = GetUi16a(p + 6);
if (algId * 64 + 128 != bitLen)
return E_NOTIMPL;
_key.KeySize = 16 + algId * 8;
const bool cert = ((flags & 2) != 0);
if ((flags & 0x4000) != 0)
if (flags & 0x4000)
{
// Use 3DES for rd data
return E_NOTIMPL;
@ -155,7 +156,7 @@ HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK)
return E_NOTIMPL;
}
UInt32 rdSize = GetUi16(p + 8);
UInt32 rdSize = GetUi16a(p + 8);
if (rdSize + 16 > _remSize)
return E_NOTIMPL;
@ -174,7 +175,7 @@ HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK)
// PKCS7 padding
if (rdSize < kPadSize)
return E_NOTIMPL;
if ((rdSize & (kPadSize - 1)) != 0)
if (rdSize & (kPadSize - 1))
return E_NOTIMPL;
}

View file

@ -115,5 +115,5 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
_x + _xSize, _y, 8, 12 // these values are unused
#define OPTIONS_PAGE_XC_SIZE 280
#define OPTIONS_PAGE_XC_SIZE 300
#define OPTIONS_PAGE_YC_SIZE 280

View file

@ -20,6 +20,8 @@
10 IFolderArchiveUpdateCallback2
11 IFolderScanProgress
12 IFolderSetZoneIdMode
13 IFolderSetZoneIdFile
14 IFolderArchiveUpdateCallback_MoveArc
20 IFileExtractCallback.h::IGetProp
30 IFileExtractCallback.h::IFolderExtractToStreamCallback (old)

View file

@ -1516,6 +1516,8 @@ Z7_COM7F_IMF(CAgentFolder::Extract(const UInt32 *indices,
if (_zoneMode != NExtract::NZoneIdMode::kNone)
{
ReadZoneFile_Of_BaseFile(us2fs(_agentSpec->_archiveFilePath), extractCallbackSpec->ZoneBuf);
if (_zoneBuf.Size() != 0)
extractCallbackSpec->ZoneBuf = _zoneBuf;
}
#endif

View file

@ -60,6 +60,7 @@ class CAgentFolder Z7_final:
public IArchiveFolderInternal,
public IInArchiveGetStream,
public IFolderSetZoneIdMode,
public IFolderSetZoneIdFile,
public IFolderOperations,
public IFolderSetFlatMode,
public CMyUnknownImp
@ -75,6 +76,7 @@ class CAgentFolder Z7_final:
Z7_COM_QI_ENTRY(IArchiveFolderInternal)
Z7_COM_QI_ENTRY(IInArchiveGetStream)
Z7_COM_QI_ENTRY(IFolderSetZoneIdMode)
Z7_COM_QI_ENTRY(IFolderSetZoneIdFile)
Z7_COM_QI_ENTRY(IFolderOperations)
Z7_COM_QI_ENTRY(IFolderSetFlatMode)
Z7_COM_QI_END
@ -91,6 +93,7 @@ class CAgentFolder Z7_final:
Z7_IFACE_COM7_IMP(IArchiveFolderInternal)
Z7_IFACE_COM7_IMP(IInArchiveGetStream)
Z7_IFACE_COM7_IMP(IFolderSetZoneIdMode)
Z7_IFACE_COM7_IMP(IFolderSetZoneIdFile)
Z7_IFACE_COM7_IMP(IFolderOperations)
Z7_IFACE_COM7_IMP(IFolderSetFlatMode)
@ -106,11 +109,11 @@ public:
int CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw);
CAgentFolder():
_proxyDirIndex(0),
_isAltStreamFolder(false),
_flatMode(false),
_loadAltStreams(false) // _loadAltStreams alt streams works in flat mode, but we don't use it now
, _zoneMode(NExtract::NZoneIdMode::kNone)
_loadAltStreams(false), // _loadAltStreams alt streams works in flat mode, but we don't use it now
_proxyDirIndex(0),
_zoneMode(NExtract::NZoneIdMode::kNone)
/* , _replaceAltStreamCharsMode(0) */
{}
@ -145,21 +148,23 @@ public:
UString GetFullPrefix(UInt32 index) const; // relative too root folder of archive
public:
bool _isAltStreamFolder;
bool _flatMode;
bool _loadAltStreams; // in Flat mode
const CProxyArc *_proxy;
const CProxyArc2 *_proxy2;
unsigned _proxyDirIndex;
bool _isAltStreamFolder;
NExtract::NZoneIdMode::EEnum _zoneMode;
CByteBuffer _zoneBuf;
// Int32 _replaceAltStreamCharsMode;
// CMyComPtr<IFolderFolder> _parentFolder;
CMyComPtr<IInFolderArchive> _agent;
CAgent *_agentSpec;
CRecordVector<CProxyItem> _items;
bool _flatMode;
bool _loadAltStreams; // in Flat mode
// Int32 _replaceAltStreamCharsMode;
NExtract::NZoneIdMode::EEnum _zoneMode;
};
class CAgent Z7_final:
public IInFolderArchive,
public IFolderArcProps,
@ -213,22 +218,22 @@ public:
CProxyArc2 *_proxy2;
CArchiveLink _archiveLink;
bool ThereIsPathProp;
// bool ThereIsAltStreamProp;
UString ArchiveType;
FStringVector _names;
FString _folderPrefix; // for new files from disk
bool _updatePathPrefix_is_AltFolder;
UString _updatePathPrefix;
CAgentFolder *_agentFolder;
UString _archiveFilePath;
UString _archiveFilePath; // it can be path of non-existing file if file is virtual
DWORD _attrib;
bool _updatePathPrefix_is_AltFolder;
bool ThereIsPathProp;
bool _isDeviceFile;
bool _isHashHandler;
FString _hashBaseFolderPrefix;
#ifndef Z7_EXTRACT_ONLY

View file

@ -22,6 +22,12 @@ Z7_COM7F_IMF(CAgentFolder::SetZoneIdMode(NExtract::NZoneIdMode::EEnum zoneMode))
return S_OK;
}
Z7_COM7F_IMF(CAgentFolder::SetZoneIdFile(const Byte *data, UInt32 size))
{
_zoneBuf.CopyFrom(data, size);
return S_OK;
}
Z7_COM7F_IMF(CAgentFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 numItems,
Int32 includeAltStreams, Int32 replaceAltStreamCharsMode,

View file

@ -62,6 +62,33 @@ static bool Delete_EmptyFolder_And_EmptySubFolders(const FString &path)
return RemoveDir(path);
}
struct C_CopyFileProgress_to_FolderCallback_MoveArc Z7_final:
public ICopyFileProgress
{
IFolderArchiveUpdateCallback_MoveArc *Callback;
HRESULT CallbackResult;
virtual DWORD CopyFileProgress(UInt64 total, UInt64 current) Z7_override
{
HRESULT res = Callback->MoveArc_Progress(total, current);
CallbackResult = res;
// we can ignore E_ABORT here, because we update archive,
// and we want to get correct archive after updating
if (res == E_ABORT)
res = S_OK;
return res == S_OK ? PROGRESS_CONTINUE : PROGRESS_CANCEL;
}
C_CopyFileProgress_to_FolderCallback_MoveArc(
IFolderArchiveUpdateCallback_MoveArc *callback) :
Callback(callback),
CallbackResult(S_OK)
{}
};
HRESULT CAgentFolder::CommonUpdateOperation(
AGENT_OP operation,
bool moveMode,
@ -159,8 +186,51 @@ HRESULT CAgentFolder::CommonUpdateOperation(
// now: we reopen archive after close
// m_FolderItem = NULL;
_items.Clear();
_proxyDirIndex = k_Proxy_RootDirIndex;
CMyComPtr<IFolderArchiveUpdateCallback_MoveArc> updateCallback_MoveArc;
if (progress)
progress->QueryInterface(IID_IFolderArchiveUpdateCallback_MoveArc, (void **)&updateCallback_MoveArc);
const HRESULT res = tempFile.MoveToOriginal(true);
HRESULT res;
if (updateCallback_MoveArc)
{
const FString &tempFilePath = tempFile.Get_TempFilePath();
UInt64 totalSize = 0;
{
NFind::CFileInfo fi;
if (fi.Find(tempFilePath))
totalSize = fi.Size;
}
RINOK(updateCallback_MoveArc->MoveArc_Start(
fs2us(tempFilePath),
fs2us(tempFile.Get_OriginalFilePath()),
totalSize,
1)) // updateMode
C_CopyFileProgress_to_FolderCallback_MoveArc prox(updateCallback_MoveArc);
res = tempFile.MoveToOriginal(
true, // deleteOriginal
&prox);
if (res == S_OK)
{
res = updateCallback_MoveArc->MoveArc_Finish();
// we don't return after E_ABORT here, because
// we want to reopen new archive still.
}
else if (prox.CallbackResult != S_OK)
res = prox.CallbackResult;
// if updating callback returned E_ABORT,
// then openCallback still can return E_ABORT also.
// So ReOpen() will return with E_ABORT.
// But we want to open archive still.
// And Before_ArcReopen() call will clear user break status in that case.
RINOK(updateCallback_MoveArc->Before_ArcReopen())
}
else
res = tempFile.MoveToOriginal(true); // deleteOriginal
// RINOK(res);
if (res == S_OK)
@ -189,10 +259,10 @@ HRESULT CAgentFolder::CommonUpdateOperation(
}
// CAgent::ReOpen() deletes _proxy and _proxy2
_items.Clear();
// _items.Clear();
_proxy = NULL;
_proxy2 = NULL;
_proxyDirIndex = k_Proxy_RootDirIndex;
// _proxyDirIndex = k_Proxy_RootDirIndex;
_isAltStreamFolder = false;

View file

@ -103,5 +103,21 @@ Z7_IFACE_CONSTR_FOLDERARC(IFolderScanProgress, 0x11)
Z7_IFACE_CONSTR_FOLDERARC(IFolderSetZoneIdMode, 0x12)
#define Z7_IFACEM_IFolderSetZoneIdFile(x) \
x(SetZoneIdFile(const Byte *data, UInt32 size)) \
Z7_IFACE_CONSTR_FOLDERARC(IFolderSetZoneIdFile, 0x13)
// if the caller calls Before_ArcReopen(), the callee must
// clear user break status, because the caller want to open archive still.
#define Z7_IFACEM_IFolderArchiveUpdateCallback_MoveArc(x) \
x(MoveArc_Start(const wchar_t *srcTempPath, const wchar_t *destFinalPath, UInt64 size, Int32 updateMode)) \
x(MoveArc_Progress(UInt64 totalSize, UInt64 currentSize)) \
x(MoveArc_Finish()) \
x(Before_ArcReopen()) \
Z7_IFACE_CONSTR_FOLDERARC(IFolderArchiveUpdateCallback_MoveArc, 0x14)
Z7_PURE_INTERFACES_END
#endif

View file

@ -57,8 +57,11 @@ WIN_OBJS = \
7ZIP_COMMON_OBJS = \
$O/FileStreams.o \
C_OBJS = \
$O/Alloc.o \
OBJS = \
$(C_OBJS) \
$(COMMON_OBJS) \
$(WIN_OBJS) \
$(SYS_OBJS) \

View file

@ -1039,6 +1039,9 @@ void CArcCmdLineParser::Parse1(const UStringVector &commandStrings,
options.TechMode = parser[NKey::kTechMode].ThereIs;
options.ShowTime = parser[NKey::kShowTime].ThereIs;
if (parser[NKey::kDisablePercents].ThereIs)
options.DisablePercents = true;
if (parser[NKey::kDisablePercents].ThereIs
|| options.StdOutMode
|| !options.IsStdOutTerminal)

View file

@ -60,6 +60,8 @@ struct CArcCmdLineOptions
bool StdInMode;
bool StdOutMode;
bool EnableHeaders;
bool DisablePercents;
bool YesToAll;
bool ShowDialog;
@ -132,6 +134,7 @@ struct CArcCmdLineOptions
StdOutMode(false),
EnableHeaders(false),
DisablePercents(false),
YesToAll(false),
ShowDialog(false),

View file

@ -140,21 +140,25 @@ static bool FindExt2(const char *p, const UString &name)
}
static const FChar * const k_ZoneId_StreamName = FTEXT(":Zone.Identifier");
static const char * const k_ZoneId_StreamName_With_Colon_Prefix = ":Zone.Identifier";
void ReadZoneFile_Of_BaseFile(CFSTR fileName2, CByteBuffer &buf)
bool Is_ZoneId_StreamName(const wchar_t *s)
{
FString fileName (fileName2);
fileName += k_ZoneId_StreamName;
return StringsAreEqualNoCase_Ascii(s, k_ZoneId_StreamName_With_Colon_Prefix + 1);
}
void ReadZoneFile_Of_BaseFile(CFSTR fileName, CByteBuffer &buf)
{
buf.Free();
FString path (fileName);
path += k_ZoneId_StreamName_With_Colon_Prefix;
NIO::CInFile file;
if (!file.Open(fileName))
if (!file.Open(path))
return;
UInt64 fileSize;
if (!file.GetLength(fileSize))
return;
if (fileSize == 0 || fileSize >= ((UInt32)1 << 16))
if (fileSize == 0 || fileSize >= (1u << 15))
return;
buf.Alloc((size_t)fileSize);
size_t processed;
@ -166,7 +170,7 @@ void ReadZoneFile_Of_BaseFile(CFSTR fileName2, CByteBuffer &buf)
bool WriteZoneFile_To_BaseFile(CFSTR fileName, const CByteBuffer &buf)
{
FString path (fileName);
path += k_ZoneId_StreamName;
path += k_ZoneId_StreamName_With_Colon_Prefix;
NIO::COutFile file;
if (!file.Create_ALWAYS(path))
return false;
@ -275,16 +279,13 @@ HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *r
CArchiveExtractCallback::CArchiveExtractCallback():
_arc(NULL),
Write_CTime(true),
Write_ATime(true),
Write_MTime(true),
// Write_CTime(true),
// Write_ATime(true),
// Write_MTime(true),
Is_elimPrefix_Mode(false),
_arc(NULL),
_multiArchives(false)
{
LocalProgressSpec = new CLocalProgress();
_localProgress = LocalProgressSpec;
#ifdef Z7_USE_SECURITY_CODE
_saclEnabled = InitLocalPrivileges();
#endif
@ -293,9 +294,9 @@ CArchiveExtractCallback::CArchiveExtractCallback():
void CArchiveExtractCallback::InitBeforeNewArchive()
{
#if defined(_WIN32) && !defined(UNDER_CE)
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)
ZoneBuf.Free();
#endif
#endif
}
void CArchiveExtractCallback::Init(
@ -322,27 +323,20 @@ void CArchiveExtractCallback::Init(
_ntOptions = ntOptions;
_wildcardCensor = wildcardCensor;
_stdOutMode = stdOutMode;
_testMode = testMode;
// _progressTotal = 0;
// _progressTotal_Defined = false;
_packTotal = packSize;
_progressTotal = packSize;
_progressTotal_Defined = true;
// _progressTotal = 0;
// _progressTotal_Defined = false;
// _progressTotal_Defined = true;
_extractCallback2 = extractCallback2;
/*
_compressProgress.Release();
_extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress);
_callbackMessage.Release();
_extractCallback2.QueryInterface(IID_IArchiveExtractCallbackMessage2, &_callbackMessage);
*/
_folderArchiveExtractCallback2.Release();
_extractCallback2.QueryInterface(IID_IFolderArchiveExtractCallback2, &_folderArchiveExtractCallback2);
@ -390,7 +384,7 @@ Z7_COM7F_IMF(CArchiveExtractCallback::SetTotal(UInt64 size))
{
COM_TRY_BEGIN
_progressTotal = size;
_progressTotal_Defined = true;
// _progressTotal_Defined = true;
if (!_multiArchives && _extractCallback2)
return _extractCallback2->SetTotal(size);
return S_OK;
@ -430,7 +424,7 @@ Z7_COM7F_IMF(CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue))
if (_multiArchives)
{
packCur = LocalProgressSpec->InSize;
if (completeValue && _progressTotal_Defined)
if (completeValue /* && _progressTotal_Defined */)
packCur += MyMultDiv64(*completeValue, _progressTotal, _packTotal);
completeValue = &packCur;
}
@ -443,7 +437,7 @@ Z7_COM7F_IMF(CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue))
Z7_COM7F_IMF(CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize))
{
COM_TRY_BEGIN
return _localProgress->SetRatioInfo(inSize, outSize);
return LocalProgressSpec.Interface()->SetRatioInfo(inSize, outSize);
COM_TRY_END
}
@ -582,13 +576,23 @@ HRESULT CArchiveExtractCallback::SendMessageError2(HRESULT errorCode, const char
#ifndef Z7_SFX
Z7_CLASS_IMP_COM_1(
CGetProp
, IGetProp
)
public:
UInt32 IndexInArc;
const CArc *Arc;
// UString BaseName; // relative path
};
Z7_COM7F_IMF(CGetProp::GetProp(PROPID propID, PROPVARIANT *value))
{
/*
if (propID == kpidName)
if (propID == kpidBaseName)
{
COM_TRY_BEGIN
NCOM::CPropVariant prop = Name;
NCOM::CPropVariant prop = BaseName;
prop.Detach(value);
return S_OK;
COM_TRY_END
@ -1087,7 +1091,7 @@ void CArchiveExtractCallback::GetFiTimesCAM(CFiTimesCAM &pt)
pt.ATime_Defined = false;
pt.MTime_Defined = false;
if (Write_MTime)
// if (Write_MTime)
{
if (_fi.MTime.Def)
{
@ -1101,13 +1105,13 @@ void CArchiveExtractCallback::GetFiTimesCAM(CFiTimesCAM &pt)
}
}
if (Write_CTime && _fi.CTime.Def)
if (/* Write_CTime && */ _fi.CTime.Def)
{
_fi.CTime.Write_To_FiTime(pt.CTime);
pt.CTime_Defined = true;
}
if (Write_ATime && _fi.ATime.Def)
if (/* Write_ATime && */ _fi.ATime.Def)
{
_fi.ATime.Write_To_FiTime(pt.ATime);
pt.ATime_Defined = true;
@ -1302,7 +1306,7 @@ HRESULT CArchiveExtractCallback::CheckExistFile(FString &fullProcessedPath, bool
{
#if defined(_WIN32) && !defined(UNDER_CE)
// we need to clear READ-ONLY of parent before creating alt stream
int colonPos = NName::FindAltStreamColon(fullProcessedPath);
const int colonPos = NName::FindAltStreamColon(fullProcessedPath);
if (colonPos >= 0 && fullProcessedPath[(unsigned)colonPos + 1] != 0)
{
FString parentFsPath (fullProcessedPath);
@ -1311,7 +1315,11 @@ HRESULT CArchiveExtractCallback::CheckExistFile(FString &fullProcessedPath, bool
if (parentFi.Find(parentFsPath))
{
if (parentFi.IsReadOnly())
{
_altStream_NeedRestore_Attrib_for_parentFsPath = parentFsPath;
_altStream_NeedRestore_AttribVal = parentFi.Attrib;
SetFileAttrib(parentFsPath, parentFi.Attrib & ~(DWORD)FILE_ATTRIBUTE_READONLY);
}
}
}
#endif // defined(_WIN32) && !defined(UNDER_CE)
@ -1607,37 +1615,37 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
_bufPtrSeqOutStream.Release();
_encrypted = false;
_position = 0;
_isSplit = false;
_curSize = 0;
_curSize_Defined = false;
_fileLength_WasSet = false;
_fileLength_that_WasSet = 0;
_index = index;
_diskFilePath.Empty();
_isRenamed = false;
// _fi.Clear();
_extractMode = false;
// _is_SymLink_in_Data = false;
_is_SymLink_in_Data_Linux = false;
_needSetAttrib = false;
_isSymLinkCreated = false;
_itemFailure = false;
_some_pathParts_wereRemoved = false;
// _op_WasReported = false;
_position = 0;
_curSize = 0;
_fileLength_that_WasSet = 0;
_index = index;
#if defined(_WIN32) && !defined(UNDER_CE)
_altStream_NeedRestore_AttribVal = 0;
_altStream_NeedRestore_Attrib_for_parentFsPath.Empty();
#endif
_diskFilePath.Empty();
#ifdef SUPPORT_LINKS
// _copyFile_Path.Empty();
_link.Clear();
#endif
_extractMode = false;
switch (askExtractMode)
{
@ -1692,6 +1700,19 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
return S_OK;
}
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)
if (askExtractMode == NArchive::NExtract::NAskMode::kExtract
&& !_testMode
&& _item.IsAltStream
&& ZoneBuf.Size() != 0
&& Is_ZoneId_StreamName(_item.AltStreamName))
if (ZoneMode != NExtract::NZoneIdMode::kOffice
|| _item.PathParts.IsEmpty()
|| FindExt2(kOfficeExtensions, _item.PathParts.Back()))
return S_OK;
#endif
#ifndef Z7_SFX
if (_use_baseParentFolder_mode)
{
@ -1810,15 +1831,11 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
if (ExtractToStreamCallback)
{
if (!GetProp)
{
GetProp_Spec = new CGetProp;
GetProp = GetProp_Spec;
}
GetProp_Spec->Arc = _arc;
GetProp_Spec->IndexInArc = index;
CMyComPtr2_Create<IGetProp, CGetProp> GetProp;
GetProp->Arc = _arc;
GetProp->IndexInArc = index;
UString name (MakePathFromParts(pathParts));
// GetProp->BaseName = name;
#ifdef SUPPORT_ALT_STREAMS
if (_item.IsAltStream)
{
@ -1984,6 +2001,15 @@ HRESULT CArchiveExtractCallback::CloseFile()
RINOK(_outFileStreamSpec->Close())
_outFileStream.Release();
#if defined(_WIN32) && !defined(UNDER_CE)
if (!_altStream_NeedRestore_Attrib_for_parentFsPath.IsEmpty())
{
SetFileAttrib(_altStream_NeedRestore_Attrib_for_parentFsPath, _altStream_NeedRestore_AttribVal);
_altStream_NeedRestore_Attrib_for_parentFsPath.Empty();
}
#endif
return hres;
}

View file

@ -90,25 +90,10 @@ struct CExtractNtOptions
}
};
#ifndef Z7_SFX
Z7_CLASS_IMP_COM_1(
CGetProp
, IGetProp
)
public:
UInt32 IndexInArc;
const CArc *Arc;
// UString Name; // relative path
};
#endif
#ifndef Z7_SFX
#ifndef UNDER_CE
#define SUPPORT_LINKS
#endif
#endif
@ -282,46 +267,44 @@ class CArchiveExtractCallback Z7_final:
Z7_IFACE_COM7_IMP(IArchiveRequestMemoryUseCallback)
#endif
// bool Write_CTime;
// bool Write_ATime;
// bool Write_MTime;
bool _stdOutMode;
bool _testMode;
bool _removePartsForAltStreams;
public:
bool Is_elimPrefix_Mode;
private:
const CArc *_arc;
CExtractNtOptions _ntOptions;
bool _isSplit;
bool _extractMode;
bool Write_CTime;
bool Write_ATime;
bool Write_MTime;
bool _keepAndReplaceEmptyDirPrefixes; // replace them to "_";
bool _encrypted;
// bool _is_SymLink_in_Data;
bool _is_SymLink_in_Data_Linux; // false = WIN32, true = LINUX
bool _needSetAttrib;
bool _isSymLinkCreated;
bool _itemFailure;
bool _some_pathParts_wereRemoved;
public:
bool Is_elimPrefix_Mode;
private:
bool _isSplit;
bool _curSize_Defined;
bool _fileLength_WasSet;
bool _removePartsForAltStreams;
bool _isRenamed;
bool _extractMode;
// bool _is_SymLink_in_Data;
bool _is_SymLink_in_Data_Linux; // false = WIN32, true = LINUX
bool _needSetAttrib;
bool _isSymLinkCreated;
bool _itemFailure;
bool _some_pathParts_wereRemoved;
bool _stdOutMode;
bool _testMode;
bool _multiArchives;
bool _keepAndReplaceEmptyDirPrefixes; // replace them to "_";
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)
bool _saclEnabled;
#endif
NExtract::NPathMode::EEnum _pathMode;
NExtract::NOverwriteMode::EEnum _overwriteMode;
const NWildcard::CCensorNode *_wildcardCensor; // we need wildcard for single pass mode (stdin)
CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2;
const NWildcard::CCensorNode *_wildcardCensor; // we need wildcard for single pass mode (stdin)
// CMyComPtr<ICompressProgressInfo> _compressProgress;
// CMyComPtr<IArchiveExtractCallbackMessage2> _callbackMessage;
CMyComPtr<IFolderArchiveExtractCallback2> _folderArchiveExtractCallback2;
@ -333,15 +316,12 @@ private:
#ifndef Z7_SFX
CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback;
CGetProp *GetProp_Spec;
CMyComPtr<IGetProp> GetProp;
CMyComPtr<IArchiveRequestMemoryUseCallback> _requestMemoryUseCallback;
#endif
CReadArcItem _item;
FString _diskFilePath;
UInt64 _position;
struct CProcessedFileInfo
{
@ -387,9 +367,17 @@ private:
}
} _fi;
UInt32 _index;
UInt64 _position;
UInt64 _curSize;
UInt64 _fileLength_that_WasSet;
UInt32 _index;
// #ifdef SUPPORT_ALT_STREAMS
#if defined(_WIN32) && !defined(UNDER_CE)
DWORD _altStream_NeedRestore_AttribVal;
FString _altStream_NeedRestore_Attrib_for_parentFsPath;
#endif
// #endif
COutFileStream *_outFileStreamSpec;
CMyComPtr<ISequentialOutStream> _outFileStream;
@ -398,9 +386,7 @@ private:
CBufPtrSeqOutStream *_bufPtrSeqOutStream_Spec;
CMyComPtr<ISequentialOutStream> _bufPtrSeqOutStream;
#ifndef Z7_SFX
COutStreamWithHash *_hashStreamSpec;
CMyComPtr<ISequentialOutStream> _hashStream;
bool _hashStreamWasUsed;
@ -411,11 +397,9 @@ private:
UStringVector _removePathParts;
CMyComPtr<ICompressProgressInfo> _localProgress;
UInt64 _packTotal;
UInt64 _progressTotal;
bool _progressTotal_Defined;
// bool _progressTotal_Defined;
CObjectVector<CDirPathTime> _extractedFolders;
@ -423,10 +407,6 @@ private:
// CObjectVector<NWindows::NFile::NDir::CDelayedSymLink> _delayedSymLinks;
#endif
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)
bool _saclEnabled;
#endif
void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath);
HRESULT GetTime(UInt32 index, PROPID propID, CArcTime &ft);
HRESULT GetUnpackSize();
@ -441,13 +421,12 @@ public:
HRESULT SendMessageError_with_LastError(const char *message, const FString &path);
HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2);
public:
#if defined(_WIN32) && !defined(UNDER_CE)
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)
NExtract::NZoneIdMode::EEnum ZoneMode;
CByteBuffer ZoneBuf;
#endif
#endif
CLocalProgress *LocalProgressSpec;
CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> LocalProgressSpec;
UInt64 NumFolders;
UInt64 NumFiles;
@ -468,11 +447,11 @@ public:
_multiArchives = multiArchives;
_pathMode = pathMode;
_overwriteMode = overwriteMode;
#if defined(_WIN32) && !defined(UNDER_CE)
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)
ZoneMode = zoneMode;
#else
#else
UNUSED_VAR(zoneMode)
#endif
#endif
_keepAndReplaceEmptyDirPrefixes = keepAndReplaceEmptyDirPrefixes;
NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0;
}
@ -551,7 +530,6 @@ private:
void GetFiTimesCAM(CFiTimesCAM &pt);
void CreateFolders();
bool _isRenamed;
HRESULT CheckExistFile(FString &fullProcessedPath, bool &needExit);
HRESULT GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit);
HRESULT GetItem(UInt32 index);
@ -599,7 +577,8 @@ struct CArchiveExtractCallback_Closer
bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);
void ReadZoneFile_Of_BaseFile(CFSTR fileName2, CByteBuffer &buf);
bool Is_ZoneId_StreamName(const wchar_t *s);
void ReadZoneFile_Of_BaseFile(CFSTR fileName, CByteBuffer &buf);
bool WriteZoneFile_To_BaseFile(CFSTR fileName, const CByteBuffer &buf);
#endif

View file

@ -2298,6 +2298,28 @@ HRESULT CCrcInfo_Base::Generate(const Byte *data, size_t size)
}
#if 1
#define HashUpdate(hf, data, size) hf->Update(data, size)
#else
// for debug:
static void HashUpdate(IHasher *hf, const void *data, UInt32 size)
{
for (;;)
{
if (size == 0)
return;
UInt32 size2 = (size * 0x85EBCA87) % size / 8;
// UInt32 size2 = size / 2;
if (size2 == 0)
size2 = 1;
hf->Update(data, size2);
data = (const void *)((const Byte *)data + size2);
size -= size2;
}
}
#endif
HRESULT CCrcInfo_Base::CrcProcess(UInt64 numIterations,
const UInt32 *checkSum, IHasher *hf,
IBenchPrintCallback *callback)
@ -2328,7 +2350,7 @@ HRESULT CCrcInfo_Base::CrcProcess(UInt64 numIterations,
const size_t rem = size - pos;
const UInt32 kStep = ((UInt32)1 << 31);
const UInt32 curSize = (rem < kStep) ? (UInt32)rem : kStep;
hf->Update(buf + pos, curSize);
HashUpdate(hf, buf + pos, curSize);
pos += curSize;
}
while (pos != size);
@ -2742,14 +2764,20 @@ static const CBenchHash g_Hash[] =
{ 2, 128 *ARM_CRC_MUL, 0x21e207bb, "CRC32:32" },
{ 2, 64 *ARM_CRC_MUL, 0x21e207bb, "CRC32:64" },
{ 10, 256, 0x41b901d1, "CRC64" },
{ 10, 64, 0x43eac94f, "XXH64" },
{ 10, 5100, 0x7913ba03, "SHA256:1" },
{ 2, CMPLX((32 * 4 + 1) * 4 + 4), 0x7913ba03, "SHA256:2" },
{ 10, 2340, 0xff769021, "SHA1:1" },
{ 5, 64, 0x43eac94f, "XXH64" },
{ 2, 2340, 0x3398a904, "MD5" },
{ 10, 2340, 0xff769021, "SHA1:1" },
{ 2, CMPLX((20 * 6 + 1) * 4 + 4), 0xff769021, "SHA1:2" },
{ 10, 5100, 0x7913ba03, "SHA256:1" },
{ 2, CMPLX((32 * 4 + 1) * 4 + 4), 0x7913ba03, "SHA256:2" },
{ 5, 3200, 0xe7aeb394, "SHA512:1" },
{ 2, CMPLX((40 * 4 + 1) * 4 + 4), 0xe7aeb394, "SHA512:2" },
// { 10, 3428, 0x1cc99b18, "SHAKE128" },
// { 10, 4235, 0x74eaddc3, "SHAKE256" },
// { 10, 4000, 0xdf3e6863, "SHA3-224" },
{ 5, 4200, 0xcecac10d, "SHA3-256" },
// { 10, 5538, 0x4e5d9163, "SHA3-384" },
// { 10, 8000, 0x96a58289, "SHA3-512" },
{ 2, 4096, 0x85189d02, "BLAKE2sp:1" },
{ 2, 1024, 0x85189d02, "BLAKE2sp:2" }, // sse2-way4-fast
{ 2, 512, 0x85189d02, "BLAKE2sp:3" } // avx2-way8-fast
@ -3687,7 +3715,7 @@ HRESULT Bench(
return E_FAIL;
UInt32 numCPUs = 1;
UInt64 ramSize = (UInt64)(sizeof(size_t)) << 29;
size_t ramSize = (size_t)sizeof(size_t) << 29;
NSystem::CProcessAffinity threadsInfo;
threadsInfo.InitST();
@ -3713,7 +3741,7 @@ HRESULT Bench(
}
*/
bool ramSize_Defined = NSystem::GetRamSize(ramSize);
const bool ramSize_Defined = NSystem::GetRamSize(ramSize);
UInt32 numThreadsSpecified = numCPUs;
bool needSetComplexity = false;
@ -4002,16 +4030,29 @@ HRESULT Bench(
}
}
if (numThreadsSpecified >= 2)
if (printCallback || freqCallback)
for (unsigned test = 0; test < 3; test++)
{
if (numThreadsSpecified < 2)
{
// if (test == 1)
break;
}
if (test == 2 && numThreadsSpecified <= numCPUs)
break;
if (printCallback)
printCallback->NewLine();
/* it can show incorrect frequency for HT threads.
so we reduce freq test to (numCPUs / 2) */
/* it can show incorrect frequency for HT threads. */
UInt32 numThreads = (numThreadsSpecified >= numCPUs / 2 ? numCPUs / 2 : numThreadsSpecified);
UInt32 numThreads = numThreadsSpecified;
if (test < 2)
{
if (numThreads >= numCPUs)
numThreads = numCPUs;
if (test == 0)
numThreads /= 2;
}
if (numThreads < 1)
numThreads = 1;
@ -4567,6 +4608,8 @@ HRESULT Bench(
if (!dictIsDefined && !onlyHashBench)
{
// we use dicSizeLog and dicSizeLog_Main for data size.
// also we use it to reduce dictionary size of LZMA encoder via NCoderPropID::kReduceSize.
const unsigned dicSizeLog_Main = (totalBenchMode ? 24 : 25);
unsigned dicSizeLog = dicSizeLog_Main;

View file

@ -671,7 +671,7 @@ static HRESULT EnumerateForItem(
}
#if defined(_WIN32)
if (needAltStreams && dirItems.ScanAltStreams)
if (needAltStreams && dirItems.ScanAltStreams && !fi.IsAltStream)
{
RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent,
phyPrefix + fi.Name, // with (fi.Name)
@ -929,7 +929,7 @@ static HRESULT EnumerateDirItems(
}
#if defined(_WIN32)
if (needAltStreams && dirItems.ScanAltStreams)
if (needAltStreams && dirItems.ScanAltStreams && !fi.IsAltStream)
{
UStringVector pathParts;
pathParts.Add(fs2us(fi.Name));

View file

@ -773,13 +773,21 @@ static const char * const k_CsumMethodNames[] =
{
"sha256"
, "sha224"
// , "sha512/224"
// , "sha512/256"
, "sha512"
// , "sha512-224"
// , "sha512-256"
, "sha384"
, "sha512"
// , "sha3-224"
, "sha3-256"
// , "sha3-384"
// , "sha3-512"
// , "shake128"
// , "shake256"
, "sha1"
, "md5"
, "blake2sp"
, "blake2b"
, "xxh64"
, "crc64"
, "crc32"
, "cksum"
@ -2076,11 +2084,27 @@ void Codecs_AddHashArcHandler(CCodecs *codecs)
// ubuntu uses "SHA256SUMS" file
item.AddExts(UString (
"sha256 sha512 sha224 sha384 sha1 sha md5"
// "b2sum"
"sha256"
" sha512"
" sha384"
" sha224"
// " sha512-224"
// " sha512-256"
// " sha3-224"
" sha3-256"
// " sha3-384"
// " sha3-512"
// " shake128"
// " shake256"
" sha1"
" sha"
" md5"
" blake2sp"
" xxh64"
" crc32 crc64"
" asc"
" cksum"
// " b2sum"
),
UString());

View file

@ -21,8 +21,8 @@
using namespace NWindows;
static const unsigned kNumWinAtrribFlags = 21;
static const char g_WinAttribChars[kNumWinAtrribFlags + 1] = "RHS8DAdNTsLCOIEV.X.PU";
static const unsigned kNumWinAtrribFlags = 30;
static const char g_WinAttribChars[kNumWinAtrribFlags + 1] = "RHS8DAdNTsLCOIEVvX.PU.M......B";
/*
FILE_ATTRIBUTE_
@ -48,8 +48,9 @@ FILE_ATTRIBUTE_
18 RECALL_ON_OPEN or EA
19 PINNED
20 UNPINNED
21 STRICTLY_SEQUENTIAL
21 STRICTLY_SEQUENTIAL (10.0.16267)
22 RECALL_ON_DATA_ACCESS
29 STRICTLY_SEQUENTIAL (10.0.17134+) (SMR Blob)
*/
@ -107,10 +108,10 @@ void ConvertWinAttribToString(char *s, UInt32 wa) throw()
for (unsigned i = 0; i < kNumWinAtrribFlags; i++)
{
UInt32 flag = (1 << i);
if ((wa & flag) != 0)
const UInt32 flag = (UInt32)1 << i;
if (wa & flag)
{
char c = g_WinAttribChars[i];
const char c = g_WinAttribChars[i];
if (c != '.')
{
wa &= ~flag;

View file

@ -13,7 +13,8 @@ void CTempFiles::Clear()
{
while (!Paths.IsEmpty())
{
NDir::DeleteFileAlways(Paths.Back());
if (NeedDeleteFiles)
NDir::DeleteFileAlways(Paths.Back());
Paths.DeleteBack();
}
}

View file

@ -10,6 +10,9 @@ class CTempFiles
void Clear();
public:
FStringVector Paths;
bool NeedDeleteFiles;
CTempFiles(): NeedDeleteFiles(true) {}
~CTempFiles() { Clear(); }
};

View file

@ -1096,6 +1096,30 @@ typedef Z7_WIN_MAPISENDMAILW FAR *Z7_WIN_LPMAPISENDMAILW;
#endif // _WIN32
struct C_CopyFileProgress_to_IUpdateCallbackUI2 Z7_final:
public ICopyFileProgress
{
IUpdateCallbackUI2 *Callback;
HRESULT CallbackResult;
// bool Disable_Break;
virtual DWORD CopyFileProgress(UInt64 total, UInt64 current) Z7_override
{
const HRESULT res = Callback->MoveArc_Progress(total, current);
CallbackResult = res;
// if (Disable_Break && res == E_ABORT) res = S_OK;
return res == S_OK ? PROGRESS_CONTINUE : PROGRESS_CANCEL;
}
C_CopyFileProgress_to_IUpdateCallbackUI2(
IUpdateCallbackUI2 *callback) :
Callback(callback),
CallbackResult(S_OK)
// , Disable_Break(false)
{}
};
HRESULT UpdateArchive(
CCodecs *codecs,
const CObjectVector<COpenType> &types,
@ -1311,7 +1335,7 @@ HRESULT UpdateArchive(
return E_NOTIMPL;
}
bool thereIsInArchive = arcLink.IsOpen;
const bool thereIsInArchive = arcLink.IsOpen;
if (!thereIsInArchive && renameMode)
return E_FAIL;
@ -1588,7 +1612,14 @@ HRESULT UpdateArchive(
multiStreams.DisableDeletion();
RINOK(multiStreams.Destruct())
tempFiles.Paths.Clear();
// here we disable deleting of temp archives.
// note: archive moving can fail, or it can be interrupted,
// if we move new temp update from another volume.
// And we still want to keep temp archive in that case,
// because we will have deleted original archive.
tempFiles.NeedDeleteFiles = false;
// tempFiles.Paths.Clear();
if (createTempFile)
{
try
@ -1603,13 +1634,52 @@ HRESULT UpdateArchive(
if (!DeleteFileAlways(us2fs(arcPath)))
return errorInfo.SetFromLastError("cannot delete the file", us2fs(arcPath));
}
if (!MyMoveFile(tempPath, us2fs(arcPath)))
UInt64 totalArcSize = 0;
{
errorInfo.SetFromLastError("cannot move the file", tempPath);
NFind::CFileInfo fi;
if (fi.Find(tempPath))
totalArcSize = fi.Size;
}
RINOK(callback->MoveArc_Start(fs2us(tempPath), arcPath,
totalArcSize, BoolToInt(thereIsInArchive)))
C_CopyFileProgress_to_IUpdateCallbackUI2 prox(callback);
// if we update archive, we have removed original archive.
// So if we break archive moving, we will have only temporary archive.
// We can disable breaking here:
// prox.Disable_Break = thereIsInArchive;
if (!MyMoveFile_with_Progress(tempPath, us2fs(arcPath), &prox))
{
errorInfo.SystemError = ::GetLastError();
errorInfo.Message = "cannot move the file";
if (errorInfo.SystemError == ERROR_INVALID_PARAMETER)
{
if (totalArcSize > (UInt32)(Int32)-1)
{
// bool isFsDetected = false;
// if (NSystem::Is_File_LimitedBy_4GB(us2fs(arcPath), isFsDetected) || !isFsDetected)
{
errorInfo.Message.Add_LF();
errorInfo.Message += "Archive file size exceeds 4 GB";
}
}
}
// if there was no input archive, and we have operation breaking.
// then we can remove temporary archive, because we still have original uncompressed files.
if (!thereIsInArchive
&& prox.CallbackResult == E_ABORT)
tempFiles.NeedDeleteFiles = true;
errorInfo.FileNames.Add(tempPath);
errorInfo.FileNames.Add(us2fs(arcPath));
RINOK(prox.CallbackResult)
return errorInfo.Get_HRESULT_Error();
}
// MoveArc_Finish() can return delayed user break (E_ABORT) status,
// if callback callee ignored interruption to finish archive creation operation.
RINOK(callback->MoveArc_Finish())
/*
if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY))

View file

@ -12,8 +12,6 @@
#include "UpdateAction.h"
#include "UpdateCallback.h"
#include "DirItem.h"
enum EArcNameMode
{
k_ArcNameMode_Smart,
@ -195,6 +193,9 @@ Z7_PURE_INTERFACES_BEGIN
virtual HRESULT FinishArchive(const CFinishArchiveStat &st) x \
virtual HRESULT DeletingAfterArchiving(const FString &path, bool isDir) x \
virtual HRESULT FinishDeletingAfterArchiving() x \
virtual HRESULT MoveArc_Start(const wchar_t *srcTempPath, const wchar_t *destFinalPath, UInt64 size, Int32 updateMode) x \
virtual HRESULT MoveArc_Progress(UInt64 total, UInt64 current) x \
virtual HRESULT MoveArc_Finish() x \
DECLARE_INTERFACE(IUpdateCallbackUI2):
public IUpdateCallbackUI,

View file

@ -63,24 +63,22 @@ HRESULT CWorkDirTempFile::CreateTempFile(const FString &originalPath)
NWorkDir::CInfo workDirInfo;
workDirInfo.Load();
FString namePart;
const FString workDir = GetWorkDir(workDirInfo, originalPath, namePart);
CreateComplexDir(workDir);
FString path = GetWorkDir(workDirInfo, originalPath, namePart);
CreateComplexDir(path);
path += namePart;
_outStreamSpec = new COutFileStream;
OutStream = _outStreamSpec;
if (!_tempFile.Create(workDir + namePart, &_outStreamSpec->File))
{
if (!_tempFile.Create(path, &_outStreamSpec->File))
return GetLastError_noZero_HRESULT();
}
_originalPath = originalPath;
return S_OK;
}
HRESULT CWorkDirTempFile::MoveToOriginal(bool deleteOriginal)
HRESULT CWorkDirTempFile::MoveToOriginal(bool deleteOriginal,
NWindows::NFile::NDir::ICopyFileProgress *progress)
{
OutStream.Release();
if (!_tempFile.MoveTo(_originalPath, deleteOriginal))
{
if (!_tempFile.MoveTo(_originalPath, deleteOriginal, progress))
return GetLastError_noZero_HRESULT();
}
return S_OK;
}

View file

@ -11,7 +11,7 @@
FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName);
class CWorkDirTempFile
class CWorkDirTempFile MY_UNCOPYABLE
{
FString _originalPath;
NWindows::NFile::NDir::CTempFile _tempFile;
@ -19,8 +19,12 @@ class CWorkDirTempFile
public:
CMyComPtr<IOutStream> OutStream;
const FString &Get_OriginalFilePath() const { return _originalPath; }
const FString &Get_TempFilePath() const { return _tempFile.GetPath(); }
HRESULT CreateTempFile(const FString &originalPath);
HRESULT MoveToOriginal(bool deleteOriginal);
HRESULT MoveToOriginal(bool deleteOriginal,
NWindows::NFile::NDir::ICopyFileProgress *progress = NULL);
};
#endif

View file

@ -45,8 +45,8 @@ static void Key_Set_UInt32(CKey &key, LPCTSTR name, UInt32 value)
static void Key_Get_UInt32(CKey &key, LPCTSTR name, UInt32 &value)
{
if (key.QueryValue(name, value) != ERROR_SUCCESS)
value = (UInt32)(Int32)-1;
value = (UInt32)(Int32)-1;
key.GetValue_UInt32_IfOk(name, value);
}
@ -59,7 +59,7 @@ static void Key_Set_BoolPair(CKey &key, LPCTSTR name, const CBoolPair &b)
static void Key_Set_bool_if_Changed(CKey &key, LPCTSTR name, bool val)
{
bool oldVal = false;
if (key.GetValue_IfOk(name, oldVal) == ERROR_SUCCESS)
if (key.GetValue_bool_IfOk(name, oldVal) == ERROR_SUCCESS)
if (val == oldVal)
return;
key.SetValue(name, val);
@ -76,13 +76,13 @@ static void Key_Set_BoolPair_Delete_IfNotDef(CKey &key, LPCTSTR name, const CBoo
static void Key_Get_BoolPair(CKey &key, LPCTSTR name, CBoolPair &b)
{
b.Val = false;
b.Def = (key.GetValue_IfOk(name, b.Val) == ERROR_SUCCESS);
b.Def = (key.GetValue_bool_IfOk(name, b.Val) == ERROR_SUCCESS);
}
static void Key_Get_BoolPair_true(CKey &key, LPCTSTR name, CBoolPair &b)
{
b.Val = true;
b.Def = (key.GetValue_IfOk(name, b.Val) == ERROR_SUCCESS);
b.Def = (key.GetValue_bool_IfOk(name, b.Val) == ERROR_SUCCESS);
}
namespace NExtract
@ -155,12 +155,12 @@ void CInfo::Load()
key.GetValue_Strings(kPathHistory, Paths);
UInt32 v;
if (key.QueryValue(kExtractMode, v) == ERROR_SUCCESS && v <= NPathMode::kAbsPaths)
if (key.GetValue_UInt32_IfOk(kExtractMode, v) == ERROR_SUCCESS && v <= NPathMode::kAbsPaths)
{
PathMode = (NPathMode::EEnum)v;
PathMode_Force = true;
}
if (key.QueryValue(kOverwriteMode, v) == ERROR_SUCCESS && v <= NOverwriteMode::kRenameExisting)
if (key.GetValue_UInt32_IfOk(kOverwriteMode, v) == ERROR_SUCCESS && v <= NOverwriteMode::kRenameExisting)
{
OverwriteMode = (NOverwriteMode::EEnum)v;
OverwriteMode_Force = true;
@ -181,7 +181,7 @@ bool Read_ShowPassword()
bool showPassword = false;
if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS)
return showPassword;
key.GetValue_IfOk(kShowPassword, showPassword);
key.GetValue_bool_IfOk(kShowPassword, showPassword);
return showPassword;
}
@ -189,13 +189,10 @@ UInt32 Read_LimitGB()
{
CS_LOCK
CKey key;
UInt32 v = (UInt32)(Int32)-1;
if (OpenMainKey(key, kKeyName) == ERROR_SUCCESS)
{
UInt32 v;
if (key.QueryValue(kMemLimit, v) == ERROR_SUCCESS)
return v;
}
return (UInt32)(Int32)-1;
key.GetValue_UInt32_IfOk(kMemLimit, v);
return v;
}
}
@ -371,9 +368,9 @@ void CInfo::Load()
UString a;
if (key.QueryValue(kArchiver, a) == ERROR_SUCCESS)
ArcType = a;
key.GetValue_IfOk(kLevel, Level);
key.GetValue_IfOk(kShowPassword, ShowPassword);
key.GetValue_IfOk(kEncryptHeaders, EncryptHeaders);
key.GetValue_UInt32_IfOk(kLevel, Level);
key.GetValue_bool_IfOk(kShowPassword, ShowPassword);
key.GetValue_bool_IfOk(kEncryptHeaders, EncryptHeaders);
}
@ -517,7 +514,7 @@ void CInfo::Load()
return;
UInt32 dirType;
if (key.QueryValue(kWorkDirType, dirType) != ERROR_SUCCESS)
if (key.GetValue_UInt32_IfOk(kWorkDirType, dirType) != ERROR_SUCCESS)
return;
switch (dirType)
{
@ -535,7 +532,7 @@ void CInfo::Load()
if (Mode == NMode::kSpecified)
Mode = NMode::kSystem;
}
key.GetValue_IfOk(kTempRemovableOnly, ForRemovableOnly);
key.GetValue_bool_IfOk(kTempRemovableOnly, ForRemovableOnly);
}
}
@ -598,5 +595,5 @@ void CContextMenuInfo::Load()
Key_Get_UInt32(key, kWriteZoneId, WriteZone);
Flags_Def = (key.GetValue_IfOk(kContextMenu, Flags) == ERROR_SUCCESS);
Flags_Def = (key.GetValue_UInt32_IfOk(kContextMenu, Flags) == ERROR_SUCCESS);
}

View file

@ -16,7 +16,7 @@
namespace NConsoleClose {
unsigned g_BreakCounter = 0;
static const unsigned kBreakAbortThreshold = 2;
static const unsigned kBreakAbortThreshold = 3;
#ifdef _WIN32
@ -28,8 +28,7 @@ static BOOL WINAPI HandlerRoutine(DWORD ctrlType)
return TRUE;
}
g_BreakCounter++;
if (g_BreakCounter < kBreakAbortThreshold)
if (++g_BreakCounter < kBreakAbortThreshold)
return TRUE;
return FALSE;
/*
@ -47,7 +46,7 @@ static BOOL WINAPI HandlerRoutine(DWORD ctrlType)
CCtrlHandlerSetter::CCtrlHandlerSetter()
{
if (!SetConsoleCtrlHandler(HandlerRoutine, TRUE))
throw "SetConsoleCtrlHandler fails";
throw 1019; // "SetConsoleCtrlHandler fails";
}
CCtrlHandlerSetter::~CCtrlHandlerSetter()
@ -63,8 +62,7 @@ CCtrlHandlerSetter::~CCtrlHandlerSetter()
static void HandlerRoutine(int)
{
g_BreakCounter++;
if (g_BreakCounter < kBreakAbortThreshold)
if (++g_BreakCounter < kBreakAbortThreshold)
return;
exit(EXIT_FAILURE);
}

View file

@ -5,7 +5,7 @@
namespace NConsoleClose {
class CCtrlBreakException {};
// class CCtrlBreakException {};
#ifdef UNDER_CE

View file

@ -343,7 +343,7 @@ Z7_COM7F_IMF(CExtractCallbackConsole::PrepareOperation(const wchar_t *name, Int3
default: s = "???"; requiredLevel = 2;
}
bool show2 = (LogLevel >= requiredLevel && _so);
const bool show2 = (LogLevel >= requiredLevel && _so);
if (show2)
{
@ -373,6 +373,7 @@ Z7_COM7F_IMF(CExtractCallbackConsole::PrepareOperation(const wchar_t *name, Int3
if (NeedFlush)
_so->Flush();
// _so->Flush(); // for debug only
}
if (NeedPercents())
@ -923,11 +924,11 @@ HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result)
}
else
{
NumArcsWithError++;
// we don't update NumArcsWithError, if error is not related to archive data.
if (result == E_ABORT
|| result == HRESULT_FROM_WIN32(ERROR_DISK_FULL)
)
|| result == HRESULT_FROM_WIN32(ERROR_DISK_FULL))
return result;
NumArcsWithError++;
if (_se)
{

View file

@ -44,7 +44,7 @@ class CExtractScanConsole Z7_final: public IDirItemsCallback
// CErrorPathCodes2 ScanErrors;
bool NeedPercents() const { return _percent._so != NULL; }
bool NeedPercents() const { return _percent._so && !_percent.DisablePrint; }
void ClosePercentsAndFlush()
{
@ -56,11 +56,16 @@ class CExtractScanConsole Z7_final: public IDirItemsCallback
public:
void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)
void Init(
CStdOutStream *outStream,
CStdOutStream *errorStream,
CStdOutStream *percentStream,
bool disablePercents)
{
_so = outStream;
_se = errorStream;
_percent._so = percentStream;
_percent.DisablePrint = disablePercents;
}
void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; }
@ -177,9 +182,13 @@ public:
void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; }
void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)
void Init(
CStdOutStream *outStream,
CStdOutStream *errorStream,
CStdOutStream *percentStream,
bool disablePercents)
{
COpenCallbackConsole::Init(outStream, errorStream, percentStream);
COpenCallbackConsole::Init(outStream, errorStream, percentStream, disablePercents);
NumTryArcs = 0;

View file

@ -1155,7 +1155,7 @@ HRESULT ListArchives(
CArchiveLink arcLink;
COpenCallbackConsole openCallback;
openCallback.Init(&g_StdOut, g_ErrStream, NULL);
openCallback.Init(&g_StdOut, g_ErrStream, NULL, listOptions.DisablePercents);
#ifndef Z7_NO_CRYPTO

View file

@ -11,10 +11,12 @@ struct CListOptions
{
bool ExcludeDirItems;
bool ExcludeFileItems;
bool DisablePercents;
CListOptions():
ExcludeDirItems(false),
ExcludeFileItems(false)
ExcludeFileItems(false),
DisablePercents(false)
{}
};

View file

@ -1280,7 +1280,9 @@ int Main2(
{
CExtractScanConsole scan;
scan.Init(options.EnableHeaders ? g_StdStream : NULL, g_ErrStream, percentsStream);
scan.Init(options.EnableHeaders ? g_StdStream : NULL,
g_ErrStream, percentsStream,
options.DisablePercents);
scan.SetWindowWidth(consoleWidth);
if (g_StdStream && options.EnableHeaders)
@ -1330,7 +1332,7 @@ int Main2(
ecs->Password = options.Password;
#endif
ecs->Init(g_StdStream, g_ErrStream, percentsStream);
ecs->Init(g_StdStream, g_ErrStream, percentsStream, options.DisablePercents);
ecs->MultiArcMode = (ArchivePathsSorted.Size() > 1);
ecs->LogLevel = options.LogLevel;
@ -1494,6 +1496,7 @@ int Main2(
CListOptions lo;
lo.ExcludeDirItems = options.Censor.ExcludeDirItems;
lo.ExcludeFileItems = options.Censor.ExcludeFileItems;
lo.DisablePercents = options.DisablePercents;
hresultMain = ListArchives(
lo,
@ -1538,7 +1541,7 @@ int Main2(
uo.SfxModule = kDefaultSfxModule;
COpenCallbackConsole openCallback;
openCallback.Init(g_StdStream, g_ErrStream, percentsStream);
openCallback.Init(g_StdStream, g_ErrStream, percentsStream, options.DisablePercents);
#ifndef Z7_NO_CRYPTO
bool passwordIsDefined =
@ -1563,7 +1566,7 @@ int Main2(
callback.StdOutMode = uo.StdOutMode;
callback.Init(
// NULL,
g_StdStream, g_ErrStream, percentsStream);
g_StdStream, g_ErrStream, percentsStream, options.DisablePercents);
CUpdateErrorInfo errorInfo;
@ -1598,7 +1601,7 @@ int Main2(
if (percentsStream)
callback.SetWindowWidth(consoleWidth);
callback.Init(g_StdStream, g_ErrStream, percentsStream);
callback.Init(g_StdStream, g_ErrStream, percentsStream, options.DisablePercents);
callback.PrintHeaders = options.EnableHeaders;
callback.PrintFields = options.ListFields;

View file

@ -140,11 +140,13 @@ int Z7_CDECL main
PrintError(kMemoryExceptionMessage);
return (NExitCode::kMemoryError);
}
/*
catch(const NConsoleClose::CCtrlBreakException &)
{
PrintError(kUserBreakMessage);
return (NExitCode::kUserBreak);
}
*/
catch(const CMessagePathException &e)
{
PrintError(kException_CmdLine_Error_Message);

View file

@ -22,7 +22,7 @@ protected:
bool _totalFilesDefined;
// bool _totalBytesDefined;
bool NeedPercents() const { return _percent._so != NULL; }
bool NeedPercents() const { return _percent._so && !_percent.DisablePrint; }
public:
@ -49,11 +49,16 @@ public:
virtual ~COpenCallbackConsole() {}
void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)
void Init(
CStdOutStream *outStream,
CStdOutStream *errorStream,
CStdOutStream *percentStream,
bool disablePercents)
{
_so = outStream;
_se = errorStream;
_percent._so = percentStream;
_percent.DisablePrint = disablePercents;
}
Z7_IFACE_IMP(IOpenCallbackUI)

View file

@ -88,6 +88,8 @@ void CPercentPrinter::GetPercents()
void CPercentPrinter::Print()
{
if (DisablePrint)
return;
DWORD tick = 0;
if (_tickStep != 0)
tick = GetTickCount();

View file

@ -26,6 +26,13 @@ struct CPercentPrinterState
class CPercentPrinter: public CPercentPrinterState
{
public:
CStdOutStream *_so;
bool DisablePrint;
bool NeedFlush;
unsigned MaxLen;
private:
UInt32 _tickStep;
DWORD _prevTick;
@ -41,16 +48,13 @@ class CPercentPrinter: public CPercentPrinterState
void GetPercents();
public:
CStdOutStream *_so;
bool NeedFlush;
unsigned MaxLen;
CPercentPrinter(UInt32 tickStep = 200):
_tickStep(tickStep),
_prevTick(0),
DisablePrint(false),
NeedFlush(true),
MaxLen(80 - 1)
MaxLen(80 - 1),
_tickStep(tickStep),
_prevTick(0)
{}
~CPercentPrinter();

View file

@ -361,6 +361,119 @@ HRESULT CUpdateCallbackConsole::WriteSfx(const wchar_t *name, UInt64 size)
}
HRESULT CUpdateCallbackConsole::MoveArc_UpdateStatus()
{
if (NeedPercents())
{
AString &s = _percent.Command;
s = " : ";
s.Add_UInt64(_arcMoving_percents);
s.Add_Char('%');
const bool totalDefined = (_arcMoving_total != 0 && _arcMoving_total != (UInt64)(Int64)-1);
if (_arcMoving_current != 0 || totalDefined)
{
s += " : ";
s.Add_UInt64(_arcMoving_current >> 20);
s += " MiB";
}
if (totalDefined)
{
s += " / ";
s.Add_UInt64((_arcMoving_total + ((1 << 20) - 1)) >> 20);
s += " MiB";
}
s += " : temporary archive moving ...";
_percent.Print();
}
// we ignore single Ctrl-C, if (_arcMoving_updateMode) mode
// because we want to get good final archive instead of temp archive.
if (NConsoleClose::g_BreakCounter == 1 && _arcMoving_updateMode)
return S_OK;
return CheckBreak();
}
HRESULT CUpdateCallbackConsole::MoveArc_Start(
const wchar_t *srcTempPath, const wchar_t *destFinalPath,
UInt64 size, Int32 updateMode)
{
#if 0 // 1 : for debug
if (LogLevel > 0 && _so)
{
ClosePercents_for_so();
*_so << "Temporary archive moving:" << endl;
_tempU = srcTempPath;
_so->Normalize_UString_Path(_tempU);
_so->PrintUString(_tempU, _tempA);
*_so << endl;
_tempU = destFinalPath;
_so->Normalize_UString_Path(_tempU);
_so->PrintUString(_tempU, _tempA);
*_so << endl;
}
#else
UNUSED_VAR(srcTempPath)
UNUSED_VAR(destFinalPath)
#endif
_arcMoving_updateMode = updateMode;
_arcMoving_total = size;
_arcMoving_current = 0;
_arcMoving_percents = 0;
return MoveArc_UpdateStatus();
}
HRESULT CUpdateCallbackConsole::MoveArc_Progress(UInt64 totalSize, UInt64 currentSize)
{
#if 0 // 1 : for debug
if (_so)
{
ClosePercents_for_so();
*_so << totalSize << " : " << currentSize << endl;
}
#endif
UInt64 percents = 0;
if (totalSize != 0)
{
if (totalSize < ((UInt64)1 << 57))
percents = currentSize * 100 / totalSize;
else
percents = currentSize / (totalSize / 100);
}
#ifdef _WIN32
// Sleep(300); // for debug
#endif
// totalSize = (UInt64)(Int64)-1; // for debug
if (percents == _arcMoving_percents)
return CheckBreak();
_arcMoving_current = currentSize;
_arcMoving_total = totalSize;
_arcMoving_percents = percents;
return MoveArc_UpdateStatus();
}
HRESULT CUpdateCallbackConsole::MoveArc_Finish()
{
// _arcMoving_percents = 0;
if (NeedPercents())
{
_percent.Command.Empty();
_percent.Print();
}
// it can return delayed user break (E_ABORT) status,
// if it ignored single CTRL+C in MoveArc_Progress().
return CheckBreak();
}
HRESULT CUpdateCallbackConsole::DeletingAfterArchiving(const FString &path, bool /* isDir */)
{
if (LogLevel > 0 && _so)

View file

@ -29,30 +29,31 @@ struct CErrorPathCodes
class CCallbackConsoleBase
{
protected:
CPercentPrinter _percent;
void CommonError(const FString &path, DWORD systemError, bool isWarning);
protected:
CStdOutStream *_so;
CStdOutStream *_se;
void CommonError(const FString &path, DWORD systemError, bool isWarning);
// void CommonError(const char *message);
HRESULT ScanError_Base(const FString &path, DWORD systemError);
HRESULT OpenFileError_Base(const FString &name, DWORD systemError);
HRESULT ReadingFileError_Base(const FString &name, DWORD systemError);
public:
bool NeedPercents() const { return _percent._so != NULL; }
bool StdOutMode;
bool NeedFlush;
unsigned PercentsNameLevel;
unsigned LogLevel;
protected:
AString _tempA;
UString _tempU;
CPercentPrinter _percent;
public:
CErrorPathCodes FailedFiles;
CErrorPathCodes ScanErrors;
UInt64 NumNonOpenFiles;
CCallbackConsoleBase():
StdOutMode(false),
@ -62,15 +63,21 @@ public:
NumNonOpenFiles(0)
{}
bool NeedPercents() const { return _percent._so != NULL; }
void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; }
void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)
void Init(
CStdOutStream *outStream,
CStdOutStream *errorStream,
CStdOutStream *percentStream,
bool disablePercents)
{
FailedFiles.Clear();
_so = outStream;
_se = errorStream;
_percent._so = percentStream;
_percent.DisablePrint = disablePercents;
}
void ClosePercents2()
@ -85,10 +92,6 @@ public:
_percent.ClosePrint(false);
}
CErrorPathCodes FailedFiles;
CErrorPathCodes ScanErrors;
UInt64 NumNonOpenFiles;
HRESULT PrintProgress(const wchar_t *name, bool isDir, const char *command, bool showInLog);
// void PrintInfoLine(const UString &s);
@ -104,6 +107,14 @@ class CUpdateCallbackConsole Z7_final:
Z7_IFACE_IMP(IUpdateCallbackUI)
Z7_IFACE_IMP(IDirItemsCallback)
Z7_IFACE_IMP(IUpdateCallbackUI2)
HRESULT MoveArc_UpdateStatus();
UInt64 _arcMoving_total;
UInt64 _arcMoving_current;
UInt64 _arcMoving_percents;
Int32 _arcMoving_updateMode;
public:
bool DeleteMessageWasShown;
@ -114,7 +125,11 @@ public:
#endif
CUpdateCallbackConsole():
DeleteMessageWasShown(false)
_arcMoving_total(0)
, _arcMoving_current(0)
, _arcMoving_percents(0)
, _arcMoving_updateMode(0)
, DeleteMessageWasShown(false)
#ifndef Z7_NO_CRYPTO
, PasswordIsDefined(false)
, AskPassword(false)

View file

@ -295,9 +295,13 @@ static const CHashCommand g_HashCommands[] =
{
{ CZipContextMenu::kHash_CRC32, "CRC-32", "CRC32" },
{ CZipContextMenu::kHash_CRC64, "CRC-64", "CRC64" },
{ CZipContextMenu::kHash_XXH64, "XXH64", "XXH64" },
{ CZipContextMenu::kHash_XXH64, "XXH64", "XXH64" },
{ CZipContextMenu::kHash_MD5, "MD5", "MD5" },
{ CZipContextMenu::kHash_SHA1, "SHA-1", "SHA1" },
{ CZipContextMenu::kHash_SHA256, "SHA-256", "SHA256" },
{ CZipContextMenu::kHash_SHA384, "SHA-384", "SHA384" },
{ CZipContextMenu::kHash_SHA512, "SHA-512", "SHA512" },
{ CZipContextMenu::kHash_SHA3_256, "SHA3-256", "SHA3-256" },
{ CZipContextMenu::kHash_BLAKE2SP, "BLAKE2sp", "BLAKE2sp" },
{ CZipContextMenu::kHash_All, "*", "*" },
{ CZipContextMenu::kHash_Generate_SHA256, "SHA-256 -> file.sha256", "SHA256" },
@ -534,7 +538,8 @@ bool FindExt(const char *p, const UString &name, CStringFinder &finder);
bool FindExt(const char *p, const UString &name, CStringFinder &finder)
{
const int dotPos = name.ReverseFind_Dot();
if (dotPos < 0 || dotPos == (int)name.Len() - 1)
int len = (int)name.Len() - (dotPos + 1);
if (len == 0 || len > 32 || dotPos < 0)
return false;
return finder.FindWord_In_LowCaseAsciiList_NoCase(p, name.Ptr(dotPos + 1));
}
@ -1337,8 +1342,12 @@ HRESULT CZipContextMenu::InvokeCommandCommon(const CCommandMapItem &cmi)
case kHash_CRC32:
case kHash_CRC64:
case kHash_XXH64:
case kHash_MD5:
case kHash_SHA1:
case kHash_SHA256:
case kHash_SHA384:
case kHash_SHA512:
case kHash_SHA3_256:
case kHash_BLAKE2SP:
case kHash_All:
case kHash_Generate_SHA256:

View file

@ -88,8 +88,12 @@ public:
kHash_CRC32,
kHash_CRC64,
kHash_XXH64,
kHash_MD5,
kHash_SHA1,
kHash_SHA256,
kHash_SHA384,
kHash_SHA512,
kHash_SHA3_256,
kHash_BLAKE2SP,
kHash_All,
kHash_Generate_SHA256,

View file

@ -116,15 +116,16 @@ Z7_CLASS_IMP_COM_3(
// DWORD m_StartTickValue;
bool m_MessageBoxIsShown;
CProgressBox _progressBox;
bool _numFilesTotalDefined;
bool _numBytesTotalDefined;
public:
bool PasswordIsDefined;
UString Password;
private:
CProgressBox _progressBox;
public:
COpenArchiveCallback()
{}

View file

@ -281,7 +281,7 @@ UInt32 CStartupInfo::QueryRegKeyValue(HKEY parentKey, const char *keyName,
return valueDefault;
UInt32 value;
if (regKey.QueryValue(valueName, value) != ERROR_SUCCESS)
if (regKey.GetValue_UInt32_IfOk(valueName, value) != ERROR_SUCCESS)
return valueDefault;
return value;
@ -295,7 +295,7 @@ bool CStartupInfo::QueryRegKeyValue(HKEY parentKey, const char *keyName,
return valueDefault;
bool value;
if (regKey.QueryValue(valueName, value) != ERROR_SUCCESS)
if (regKey.GetValue_bool_IfOk(valueName, value) != ERROR_SUCCESS)
return valueDefault;
return value;

View file

@ -45,7 +45,12 @@ class CProgressBox: public CPercentPrinterState
DWORD _prevElapsedSec;
bool _wasPrinted;
public:
bool UseBytesForPercents;
DWORD StartTick;
unsigned MaxLen;
private:
UString _tempU;
UString _name1U;
UString _name2U;
@ -64,15 +69,12 @@ class CProgressBox: public CPercentPrinterState
void ReduceString(const UString &src, AString &dest);
public:
DWORD StartTick;
bool UseBytesForPercents;
unsigned MaxLen;
CProgressBox(UInt32 tickStep = 200):
_tickStep(tickStep),
_prevTick(0),
StartTick(0),
UseBytesForPercents(true),
StartTick(0),
MaxLen(60)
{}

View file

@ -210,6 +210,96 @@ Z7_COM7F_IMF(CUpdateCallback100Imp::ReportUpdateOperation(UInt32 op, const wchar
}
HRESULT CUpdateCallback100Imp::MoveArc_UpdateStatus()
{
MT_LOCK
if (_percent)
{
AString s;
s.Add_UInt64(_arcMoving_percents);
// status.Add_Space();
s.Add_Char('%');
const bool totalDefined = (_arcMoving_total != 0 && _arcMoving_total != (UInt64)(Int64)-1);
if (_arcMoving_current != 0 || totalDefined)
{
s += " : ";
s.Add_UInt64(_arcMoving_current >> 20);
s += " MiB";
}
if (totalDefined)
{
s += " / ";
s.Add_UInt64((_arcMoving_total + ((1 << 20) - 1)) >> 20);
s += " MiB";
}
s += " : temporary archive moving ...";
_percent->Command = s;
_percent->Print();
}
return CheckBreak2();
}
Z7_COM7F_IMF(CUpdateCallback100Imp::MoveArc_Start(const wchar_t *srcTempPath, const wchar_t * /* destFinalPath */ , UInt64 size, Int32 /* updateMode */))
{
MT_LOCK
_arcMoving_total = size;
_arcMoving_current = 0;
_arcMoving_percents = 0;
// _arcMoving_updateMode = updateMode;
// _name2 = fs2us(destFinalPath);
if (_percent)
_percent->FileName = srcTempPath;
return MoveArc_UpdateStatus();
}
Z7_COM7F_IMF(CUpdateCallback100Imp::MoveArc_Progress(UInt64 totalSize, UInt64 currentSize))
{
UInt64 percents = 0;
if (totalSize != 0)
{
if (totalSize < ((UInt64)1 << 57))
percents = currentSize * 100 / totalSize;
else
percents = currentSize / (totalSize / 100);
}
#ifdef _WIN32
// Sleep(300); // for debug
#endif
if (percents == _arcMoving_percents)
return CheckBreak2();
_arcMoving_total = totalSize;
_arcMoving_current = currentSize;
_arcMoving_percents = percents;
// if (_arcMoving_percents > 100) return E_FAIL;
return MoveArc_UpdateStatus();
}
Z7_COM7F_IMF(CUpdateCallback100Imp::MoveArc_Finish())
{
// _arcMoving_percents = 0;
if (_percent)
{
_percent->Command.Empty();
_percent->FileName.Empty();
_percent->Print();
}
return CheckBreak2();
}
Z7_COM7F_IMF(CUpdateCallback100Imp::Before_ArcReopen())
{
// fixme: we can use Clear_Stop_Status() here
return CheckBreak2();
}
extern HRESULT GetPassword(UString &password);
Z7_COM7F_IMF(CUpdateCallback100Imp::CryptoGetTextPassword(BSTR *password))

View file

@ -11,10 +11,11 @@
#include "ProgressBox.h"
Z7_CLASS_IMP_COM_6(
Z7_CLASS_IMP_COM_7(
CUpdateCallback100Imp
, IFolderArchiveUpdateCallback
, IFolderArchiveUpdateCallback2
, IFolderArchiveUpdateCallback_MoveArc
, IFolderScanProgress
, ICryptoGetTextPassword2
, ICryptoGetTextPassword
@ -25,6 +26,15 @@ Z7_CLASS_IMP_COM_6(
// CMyComPtr<IInFolderArchive> _archiveHandler;
CProgressBox *_percent;
// UInt64 _total;
HRESULT MoveArc_UpdateStatus();
private:
UInt64 _arcMoving_total;
UInt64 _arcMoving_current;
UInt64 _arcMoving_percents;
// Int32 _arcMoving_updateMode;
public:
bool PasswordIsDefined;
UString Password;
@ -38,6 +48,10 @@ public:
_percent = progressBox;
PasswordIsDefined = false;
Password.Empty();
_arcMoving_total = 0;
_arcMoving_current = 0;
_arcMoving_percents = 0;
// _arcMoving_updateMode = 0;
}
};

View file

@ -387,8 +387,8 @@ Z7_COM7F_IMF(CAltStreamsFolder::WasChanged(Int32 *wasChanged))
return S_OK;
}
DWORD waitResult = ::WaitForSingleObject(_findChangeNotification, 0);
bool wasChangedLoc = (waitResult == WAIT_OBJECT_0);
const DWORD waitResult = ::WaitForSingleObject(_findChangeNotification, 0);
const bool wasChangedLoc = (waitResult == WAIT_OBJECT_0);
if (wasChangedLoc)
{
_findChangeNotification.FindNext();
@ -666,16 +666,10 @@ Z7_COM7F_IMF(CAltStreamsFolder::SetProperty(UInt32 /* index */, PROPID /* propID
Z7_COM7F_IMF(CAltStreamsFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex))
{
const CAltStream &ss = Streams[index];
*iconIndex = 0;
int iconIndexTemp;
if (GetRealIconIndex(_pathPrefix + us2fs(ss.Name),
0 // fi.Attrib
, iconIndexTemp) != 0)
{
*iconIndex = iconIndexTemp;
return S_OK;
}
return GetLastError_noZero_HRESULT();
return Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(
_pathPrefix + us2fs(ss.Name),
FILE_ATTRIBUTE_ARCHIVE,
iconIndex);
}
/*

View file

@ -402,11 +402,17 @@ void CApp::Save()
// Save_ShowDeleted(ShowDeletedFiles);
}
void CApp::Release()
void CApp::ReleaseApp()
{
// 24.09: ReleasePanel() will stop panel timer processing.
// but we want to stop timer processing for all panels
// before ReleasePanel() calling.
unsigned i;
for (i = 0; i < kNumPanelsMax; i++)
Panels[i].Disable_Processing_Timer_Notify_StatusBar();
// It's for unloading COM dll's: don't change it.
for (unsigned i = 0; i < kNumPanelsMax; i++)
Panels[i].Release();
for (i = 0; i < kNumPanelsMax; i++)
Panels[i].ReleasePanel();
}
// reduces path to part that exists on disk (or root prefix of path)
@ -644,7 +650,7 @@ void CApp::OnCopy(bool move, bool copyToSame, unsigned srcPanelIndex)
destPath += correctName;
#if defined(_WIN32) && !defined(UNDER_CE)
if (destPath.Len() > 0 && destPath[0] == '\\')
if (destPath.Len() != 0 && destPath[0] == '\\')
if (destPath.Len() == 1 || destPath[1] != '\\')
{
srcPanel.MessageBox_Error_UnsupportOperation();
@ -782,6 +788,7 @@ void CApp::OnCopy(bool move, bool copyToSame, unsigned srcPanelIndex)
if (useSrcPanel)
{
CCopyToOptions options;
// options.src_Is_IO_FS_Folder = useFullItemPaths;
options.folder = useTemp ? fs2us(tempDirPrefix) : destPath;
options.moveMode = move;
options.includeAltStreams = true;

View file

@ -109,7 +109,7 @@ public:
HRESULT Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool needOpenArc, COpenResult &openRes);
void Read();
void Save();
void Release();
void ReleaseApp();
// void SetFocus(int panelIndex) { Panels[panelIndex].SetFocusToList(); }
void SetFocusToLastItem() { Panels[LastFocusedPanel].SetFocusToLastRememberedItem(); }

View file

@ -208,8 +208,8 @@ bool CBrowseDialog::OnInit()
_filterCombo.SetCurSel(FilterIndex);
}
_list.SetImageList(GetSysImageList(true), LVSIL_SMALL);
_list.SetImageList(GetSysImageList(false), LVSIL_NORMAL);
_list.SetImageList(Shell_Get_SysImageList_smallIcons(true), LVSIL_SMALL);
_list.SetImageList(Shell_Get_SysImageList_smallIcons(false), LVSIL_NORMAL);
_list.InsertColumn(0, LangString(IDS_PROP_NAME), 100);
_list.InsertColumn(1, LangString(IDS_PROP_MTIME), 100);
@ -690,19 +690,21 @@ HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selected
#ifndef UNDER_CE
if (isDrive)
{
if (GetRealIconIndex(fi.Name + FCHAR_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, item.iImage) == 0)
item.iImage = 0;
item.iImage = Shell_GetFileInfo_SysIconIndex_for_Path(
fi.Name + FCHAR_PATH_SEPARATOR,
FILE_ATTRIBUTE_DIRECTORY);
}
else
#endif
item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, fullPath);
if (item.iImage < 0)
item.iImage = 0;
item.iImage = 0;
_list.InsertItem(&item);
wchar_t s[64];
{
s[0] = 0;
ConvertUtcFileTimeToString(fi.MTime, s,
if (!FILETIME_IsZero(fi.MTime))
ConvertUtcFileTimeToString(fi.MTime, s,
#ifndef UNDER_CE
kTimestampPrintLevel_MIN
#else

View file

@ -356,8 +356,8 @@ bool CBrowseDialog2::OnInit()
#endif
}
_list.SetImageList(GetSysImageList(true), LVSIL_SMALL);
_list.SetImageList(GetSysImageList(false), LVSIL_NORMAL);
_list.SetImageList(Shell_Get_SysImageList_smallIcons(true), LVSIL_SMALL);
_list.SetImageList(Shell_Get_SysImageList_smallIcons(false), LVSIL_NORMAL);
unsigned columnIndex = 0;
_list.InsertColumn(columnIndex++, LangString(IDS_PROP_NAME), 100);
@ -939,7 +939,8 @@ void CBrowseDialog2::OnDelete(/* bool toRecycleBin */)
s.Add_LF();
s += s2;
}
if (::MessageBoxW((HWND)*this, s, LangString(titleID), MB_OKCANCEL | MB_ICONQUESTION) != IDOK)
if (::MessageBoxW((HWND)*this, s, LangString(titleID),
MB_YESNOCANCEL | MB_ICONQUESTION) != IDYES)
return;
}
@ -1638,15 +1639,15 @@ HRESULT CBrowseDialog2::Reload(const UString &pathPrefix, const UStringVector &s
#ifndef UNDER_CE
if (isDrive)
{
if (GetRealIconIndex(fi.Name + FCHAR_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, item.iImage) == 0)
item.iImage = 0;
item.iImage = Shell_GetFileInfo_SysIconIndex_for_Path(
fi.Name + FCHAR_PATH_SEPARATOR,
FILE_ATTRIBUTE_DIRECTORY);
}
else
#endif
item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, fullPath);
if (item.iImage < 0)
item.iImage = 0;
item.iImage = 0;
_list.InsertItem(&item);
wchar_t s[64];
{
@ -1661,7 +1662,6 @@ HRESULT CBrowseDialog2::Reload(const UString &pathPrefix, const UStringVector &s
);
_list.SetSubItem(index, subItem++, s);
}
{
s[0] = 0;
Browse_ConvertSizeToString(bi, s);

Some files were not shown because too many files have changed in this diff Show more