mirror of
				https://github.com/Cisco-Talos/clamav.git
				synced 2025-10-31 16:10:54 +00:00 
			
		
		
		
	
		
			
	
	
		
			148 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			148 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|   | _forceinline void Unpack::InsertOldDist(uint Distance) | ||
|  | { | ||
|  |   OldDist[3]=OldDist[2]; | ||
|  |   OldDist[2]=OldDist[1]; | ||
|  |   OldDist[1]=OldDist[0]; | ||
|  |   OldDist[0]=Distance; | ||
|  | } | ||
|  | 
 | ||
|  | #ifdef _MSC_VER
 | ||
|  | #define FAST_MEMCPY
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | _forceinline void Unpack::CopyString(uint Length,uint Distance) | ||
|  | { | ||
|  |   size_t SrcPtr=UnpPtr-Distance; | ||
|  |   if (SrcPtr<MaxWinSize-MAX_INC_LZ_MATCH && UnpPtr<MaxWinSize-MAX_INC_LZ_MATCH) | ||
|  |   { | ||
|  |     // If we are not close to end of window, we do not need to waste time
 | ||
|  |     // to "& MaxWinMask" pointer protection.
 | ||
|  | 
 | ||
|  |     byte *Src=Window+SrcPtr; | ||
|  |     byte *Dest=Window+UnpPtr; | ||
|  |     UnpPtr+=Length; | ||
|  | 
 | ||
|  | #ifdef FAST_MEMCPY
 | ||
|  |     if (Distance<Length) // Overlapping strings
 | ||
|  | #endif
 | ||
|  |       while (Length>=8) | ||
|  |       { | ||
|  |         Dest[0]=Src[0]; | ||
|  |         Dest[1]=Src[1]; | ||
|  |         Dest[2]=Src[2]; | ||
|  |         Dest[3]=Src[3]; | ||
|  |         Dest[4]=Src[4]; | ||
|  |         Dest[5]=Src[5]; | ||
|  |         Dest[6]=Src[6]; | ||
|  |         Dest[7]=Src[7]; | ||
|  | 
 | ||
|  |         Src+=8; | ||
|  |         Dest+=8; | ||
|  |         Length-=8; | ||
|  |       } | ||
|  | #ifdef FAST_MEMCPY
 | ||
|  |     else | ||
|  |       while (Length>=8) | ||
|  |       { | ||
|  |         // In theory we still could overlap here.
 | ||
|  |         // Supposing Distance == MaxWinSize - 1 we have memcpy(Src, Src + 1, 8).
 | ||
|  |         // But for real RAR archives Distance <= MaxWinSize - MAX_INC_LZ_MATCH
 | ||
|  |         // always, so overlap here is impossible.
 | ||
|  | 
 | ||
|  |         // This memcpy expanded inline by MSVC. We could also use uint64
 | ||
|  |         // assignment, which seems to provide about the same speed.
 | ||
|  |         memcpy(Dest,Src,8);  | ||
|  | 
 | ||
|  |         Src+=8; | ||
|  |         Dest+=8; | ||
|  |         Length-=8; | ||
|  |       } | ||
|  | #endif
 | ||
|  | 
 | ||
|  |     // Unroll the loop for 0 - 7 bytes left. Note that we use nested "if"s.
 | ||
|  |     if (Length>0) { Dest[0]=Src[0]; | ||
|  |     if (Length>1) { Dest[1]=Src[1]; | ||
|  |     if (Length>2) { Dest[2]=Src[2]; | ||
|  |     if (Length>3) { Dest[3]=Src[3]; | ||
|  |     if (Length>4) { Dest[4]=Src[4]; | ||
|  |     if (Length>5) { Dest[5]=Src[5]; | ||
|  |     if (Length>6) { Dest[6]=Src[6]; } } } } } } } // Close all nested "if"s.
 | ||
|  |   } | ||
|  |   else | ||
|  |     while (Length-- > 0) // Slow copying with all possible precautions.
 | ||
|  |     { | ||
|  |       Window[UnpPtr]=Window[SrcPtr++ & MaxWinMask]; | ||
|  |       // We need to have masked UnpPtr after quit from loop, so it must not
 | ||
|  |       // be replaced with 'Window[UnpPtr++ & MaxWinMask]'
 | ||
|  |       UnpPtr=(UnpPtr+1) & MaxWinMask; | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | _forceinline uint Unpack::DecodeNumber(BitInput &Inp,DecodeTable *Dec) | ||
|  | { | ||
|  |   // Left aligned 15 bit length raw bit field.
 | ||
|  |   uint BitField=Inp.getbits() & 0xfffe; | ||
|  | 
 | ||
|  |   if (BitField<Dec->DecodeLen[Dec->QuickBits]) | ||
|  |   { | ||
|  |     uint Code=BitField>>(16-Dec->QuickBits); | ||
|  |     Inp.addbits(Dec->QuickLen[Code]); | ||
|  |     return Dec->QuickNum[Code]; | ||
|  |   } | ||
|  | 
 | ||
|  |   // Detect the real bit length for current code.
 | ||
|  |   uint Bits=15; | ||
|  |   for (uint I=Dec->QuickBits+1;I<15;I++) | ||
|  |     if (BitField<Dec->DecodeLen[I]) | ||
|  |     { | ||
|  |       Bits=I; | ||
|  |       break; | ||
|  |     } | ||
|  | 
 | ||
|  |   Inp.addbits(Bits); | ||
|  |    | ||
|  |   // Calculate the distance from the start code for current bit length.
 | ||
|  |   uint Dist=BitField-Dec->DecodeLen[Bits-1]; | ||
|  | 
 | ||
|  |   // Start codes are left aligned, but we need the normal right aligned
 | ||
|  |   // number. So we shift the distance to the right.
 | ||
|  |   Dist>>=(16-Bits); | ||
|  | 
 | ||
|  |   // Now we can calculate the position in the code list. It is the sum
 | ||
|  |   // of first position for current bit length and right aligned distance
 | ||
|  |   // between our bit field and start code for current bit length.
 | ||
|  |   uint Pos=Dec->DecodePos[Bits]+Dist; | ||
|  | 
 | ||
|  |   // Out of bounds safety check required for damaged archives.
 | ||
|  |   if (Pos>=Dec->MaxNum) | ||
|  |     Pos=0; | ||
|  | 
 | ||
|  |   // Convert the position in the code list to position in alphabet
 | ||
|  |   // and return it.
 | ||
|  |   return Dec->DecodeNum[Pos]; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | _forceinline uint Unpack::SlotToLength(BitInput &Inp,uint Slot) | ||
|  | { | ||
|  |   uint LBits,Length=2; | ||
|  |   if (Slot<8) | ||
|  |   { | ||
|  |     LBits=0; | ||
|  |     Length+=Slot; | ||
|  |   } | ||
|  |   else | ||
|  |   { | ||
|  |     LBits=Slot/4-1; | ||
|  |     Length+=(4 | (Slot & 3)) << LBits; | ||
|  |   } | ||
|  | 
 | ||
|  |   if (LBits>0) | ||
|  |   { | ||
|  |     Length+=Inp.getbits()>>(16-LBits); | ||
|  |     Inp.addbits(LBits); | ||
|  |   } | ||
|  |   return Length; | ||
|  | } |