@@ -413,9 +413,10 @@ bool EXECodec::inverseX86(SliceArray<kanzi::byte>& input, SliceArray<kanzi::byte
413413
414414 // Current instruction is a jump/call. Decode absolute address
415415 const int addr = BigEndian::readInt32 (&src[srcIdx + 1 ]) ^ MASK_ADDRESS ;
416- const int offset = addr - dstIdx;
416+ const int64 offset = int64 (addr) - int64 (dstIdx);
417+ const int32 encodedOffset = (offset >= 0 ) ? int32 (offset) : -int32 ((-offset) & X86_ADDR_MASK );
417418 dst[dstIdx++] = src[srcIdx++];
418- LittleEndian::writeInt32 (&dst[dstIdx], (offset >= 0 ) ? offset : -(-offset & X86_ADDR_MASK ) );
419+ LittleEndian::writeInt32 (&dst[dstIdx], encodedOffset );
419420 srcIdx += 4 ;
420421 dstIdx += 4 ;
421422 }
@@ -623,17 +624,34 @@ kanzi::byte EXECodec::detectType(const kanzi::byte src[], int count, int& codeSt
623624 return NOT_EXE | kanzi::byte (dt);
624625}
625626
627+ static bool setCodeRange (int count, int & codeStart, int & codeEnd, int64 start, int64 length)
628+ {
629+ if ((start < 0 ) || (length < 0 ) || (start > int64 (count)) || (length > int64 (count) - start))
630+ return false ;
631+
632+ if (codeStart == 0 )
633+ codeStart = int (start);
634+
635+ codeEnd = int (start + length);
636+ return true ;
637+ }
638+
626639// Return true if known header
627640bool EXECodec::parseHeader (const kanzi::byte src[], int count, uint magic, int & arch, int & codeStart, int & codeEnd)
628641{
642+
629643 if (magic == Magic::WIN_MAGIC ) {
630644 if (count >= 64 ) {
631645 const int posPE = LittleEndian::readInt32 (&src[60 ]);
632646
633647 if ((posPE > 0 ) && (posPE <= count - 48 ) && (LittleEndian::readInt32 (&src[posPE]) == WIN_PE )) {
634648 const kanzi::byte* pe = &src[posPE];
635- codeStart = min (LittleEndian::readInt32 (&pe[44 ]), count);
636- codeEnd = min (codeStart + LittleEndian::readInt32 (&pe[28 ]), count);
649+
650+ if (setCodeRange (count, codeStart, codeEnd,
651+ int64 (LittleEndian::readInt32 (&pe[44 ])),
652+ int64 (LittleEndian::readInt32 (&pe[28 ]))) == false )
653+ return false ;
654+
637655 arch = LittleEndian::readInt16 (&pe[4 ]);
638656 }
639657
@@ -648,48 +666,50 @@ bool EXECodec::parseHeader(const kanzi::byte src[], int count, uint magic, int&
648666 if (isLittleEndian == true ) {
649667 if (src[4 ] == kanzi::byte (2 )) {
650668 // 64 bits
651- int nbEntries = int (LittleEndian::readInt16 (&src[0x3C ]));
652- int szEntry = int (LittleEndian::readInt16 (&src[0x3A ]));
653- int posSection = int (LittleEndian::readLong64 (&src[0x28 ]));
669+ const int nbEntries = int (LittleEndian::readInt16 (&src[0x3C ]));
670+ const int szEntry = int (LittleEndian::readInt16 (&src[0x3A ]));
671+ const int64 posSection = LittleEndian::readLong64 (&src[0x28 ]);
672+
673+ if ((szEntry <= 0 ) || (posSection < 0 ) || (posSection > int64 (count) - 0x28 ))
674+ return false ;
654675
655676 for (int i = 0 ; i < nbEntries; i++) {
656- int startEntry = posSection + i * szEntry;
677+ const int64 startEntry = posSection + int64 (i) * int64 ( szEntry) ;
657678
658- if (startEntry + 0x28 >= count)
679+ if (startEntry > int64 ( count) - 0x28 )
659680 return false ;
660681
661682 int typeSection = int (LittleEndian::readInt32 (&src[startEntry + 4 ]));
662- int offSection = int ( LittleEndian::readLong64 (&src[startEntry + 0x18 ]) );
663- int lenSection = int ( LittleEndian::readLong64 (&src[startEntry + 0x20 ]) );
683+ const int64 offSection = LittleEndian::readLong64 (&src[startEntry + 0x18 ]);
684+ const int64 lenSection = LittleEndian::readLong64 (&src[startEntry + 0x20 ]);
664685
665686 if ((typeSection == 1 ) && (lenSection >= 64 )) {
666- if (codeStart == 0 )
667- codeStart = offSection;
668-
669- codeEnd = offSection + lenSection;
687+ if (setCodeRange (count, codeStart, codeEnd, offSection, lenSection) == false )
688+ return false ;
670689 }
671690 }
672691 } else {
673692 // 32 bits
674- int nbEntries = int (LittleEndian::readInt16 (&src[0x30 ]));
675- int szEntry = int (LittleEndian::readInt16 (&src[0x2E ]));
676- int posSection = int (LittleEndian::readInt32 (&src[0x20 ]));
693+ const int nbEntries = int (LittleEndian::readInt16 (&src[0x30 ]));
694+ const int szEntry = int (LittleEndian::readInt16 (&src[0x2E ]));
695+ const int64 posSection = int64 (LittleEndian::readInt32 (&src[0x20 ]));
696+
697+ if ((szEntry <= 0 ) || (posSection < 0 ) || (posSection > int64 (count) - 0x18 ))
698+ return false ;
677699
678700 for (int i = 0 ; i < nbEntries; i++) {
679- int startEntry = posSection + i * szEntry;
701+ const int64 startEntry = posSection + int64 (i) * int64 ( szEntry) ;
680702
681- if (startEntry + 0x18 >= count)
703+ if (startEntry > int64 ( count) - 0x18 )
682704 return false ;
683705
684706 int typeSection = int (LittleEndian::readInt32 (&src[startEntry + 4 ]));
685- int offSection = int (LittleEndian::readInt32 (&src[startEntry + 0x10 ]));
686- int lenSection = int (LittleEndian::readInt32 (&src[startEntry + 0x14 ]));
707+ const int64 offSection = int64 (LittleEndian::readInt32 (&src[startEntry + 0x10 ]));
708+ const int64 lenSection = int64 (LittleEndian::readInt32 (&src[startEntry + 0x14 ]));
687709
688710 if ((typeSection == 1 ) && (lenSection >= 64 )) {
689- if (codeStart == 0 )
690- codeStart = offSection;
691-
692- codeEnd = offSection + lenSection;
711+ if (setCodeRange (count, codeStart, codeEnd, offSection, lenSection) == false )
712+ return false ;
693713 }
694714 }
695715 }
@@ -698,48 +718,50 @@ bool EXECodec::parseHeader(const kanzi::byte src[], int count, uint magic, int&
698718 } else {
699719 if (src[4 ] == kanzi::byte (2 )) {
700720 // 64 bits
701- int nbEntries = int (BigEndian::readInt16 (&src[0x3C ]));
702- int szEntry = int (BigEndian::readInt16 (&src[0x3A ]));
703- int posSection = int (BigEndian::readLong64 (&src[0x28 ]));
721+ const int nbEntries = int (BigEndian::readInt16 (&src[0x3C ]));
722+ const int szEntry = int (BigEndian::readInt16 (&src[0x3A ]));
723+ const int64 posSection = BigEndian::readLong64 (&src[0x28 ]);
724+
725+ if ((szEntry <= 0 ) || (posSection < 0 ) || (posSection > int64 (count) - 0x28 ))
726+ return false ;
704727
705728 for (int i = 0 ; i < nbEntries; i++) {
706- int startEntry = posSection + i * szEntry;
729+ const int64 startEntry = posSection + int64 (i) * int64 ( szEntry) ;
707730
708- if (startEntry + 0x28 >= count)
731+ if (startEntry > int64 ( count) - 0x28 )
709732 return false ;
710733
711734 int typeSection = int (BigEndian::readInt32 (&src[startEntry + 4 ]));
712- int offSection = int ( BigEndian::readLong64 (&src[startEntry + 0x18 ]) );
713- int lenSection = int ( BigEndian::readLong64 (&src[startEntry + 0x20 ]) );
735+ const int64 offSection = BigEndian::readLong64 (&src[startEntry + 0x18 ]);
736+ const int64 lenSection = BigEndian::readLong64 (&src[startEntry + 0x20 ]);
714737
715738 if ((typeSection == 1 ) && (lenSection >= 64 )) {
716- if (codeStart == 0 )
717- codeStart = offSection;
718-
719- codeEnd = offSection + lenSection;
739+ if (setCodeRange (count, codeStart, codeEnd, offSection, lenSection) == false )
740+ return false ;
720741 }
721742 }
722743 } else {
723744 // 32 bits
724- int nbEntries = int (BigEndian::readInt16 (&src[0x30 ]));
725- int szEntry = int (BigEndian::readInt16 (&src[0x2E ]));
726- int posSection = int (BigEndian::readInt32 (&src[0x20 ]));
745+ const int nbEntries = int (BigEndian::readInt16 (&src[0x30 ]));
746+ const int szEntry = int (BigEndian::readInt16 (&src[0x2E ]));
747+ const int64 posSection = int64 (BigEndian::readInt32 (&src[0x20 ]));
748+
749+ if ((szEntry <= 0 ) || (posSection < 0 ) || (posSection > int64 (count) - 0x18 ))
750+ return false ;
727751
728752 for (int i = 0 ; i < nbEntries; i++) {
729- int startEntry = posSection + i * szEntry;
753+ const int64 startEntry = posSection + int64 (i) * int64 ( szEntry) ;
730754
731- if (startEntry + 0x18 >= count)
755+ if (startEntry > int64 ( count) - 0x18 )
732756 return false ;
733757
734758 int typeSection = int (BigEndian::readInt32 (&src[startEntry + 4 ]));
735- int offSection = int (BigEndian::readInt32 (&src[startEntry + 0x10 ]));
736- int lenSection = int (BigEndian::readInt32 (&src[startEntry + 0x14 ]));
759+ const int64 offSection = int64 (BigEndian::readInt32 (&src[startEntry + 0x10 ]));
760+ const int64 lenSection = int64 (BigEndian::readInt32 (&src[startEntry + 0x14 ]));
737761
738762 if ((typeSection == 1 ) && (lenSection >= 64 )) {
739- if (codeStart == 0 )
740- codeStart = offSection;
741-
742- codeEnd = offSection + lenSection;
763+ if (setCodeRange (count, codeStart, codeEnd, offSection, lenSection) == false )
764+ return false ;
743765 }
744766 }
745767 }
@@ -770,29 +792,43 @@ bool EXECodec::parseHeader(const kanzi::byte src[], int count, uint magic, int&
770792 int cmd = 0 ;
771793
772794 while (cmd < nbCmds) {
795+ if ((pos < 0 ) || (pos > count - 8 ))
796+ return false ;
797+
773798 int ldCmd = LittleEndian::readInt32 (&src[pos]);
774799 int szCmd = LittleEndian::readInt32 (&src[pos + 4 ]);
775800 int szSegHdr = (is64Bits == true ) ? 0x48 : 0x38 ;
776801
802+ if ((szCmd < 8 ) || (szCmd > count - pos))
803+ return false ;
804+
777805 if ((ldCmd == MAC_LC_SEGMENT ) || (ldCmd == MAC_LC_SEGMENT64 )) {
778- if (pos + 14 >= count)
806+ if (( pos > count - 14 ) || (pos > count - szSegHdr) )
779807 return false ;
780808
781809 if (memcmp (&src[pos + 8 ], reinterpret_cast <kanzi::byte*>(MAC_TEXT_SEGMENT ), 6 ) == 0 ) {
782810 int posSection = pos + szSegHdr;
783811
784- if (posSection + 0x34 >= count)
812+ const int minSectionSize = (is64Bits == true ) ? 0x38 : 0x30 ;
813+
814+ if (posSection > count - minSectionSize)
785815 return false ;
786816
787817 if (memcmp (&src[posSection], reinterpret_cast <kanzi::byte*>(MAC_TEXT_SECTION ), 6 ) == 0 ) {
788818 // Text section in TEXT segment
789819 if (is64Bits == true ) {
790- codeStart = int (LittleEndian::readLong64 (&src[posSection + 0x30 ]));
791- codeEnd = codeStart + LittleEndian::readInt32 (&src[posSection + 0x28 ]);
820+ if (setCodeRange (count, codeStart, codeEnd,
821+ LittleEndian::readLong64 (&src[posSection + 0x30 ]),
822+ int64 (LittleEndian::readInt32 (&src[posSection + 0x28 ]))) == false )
823+ return false ;
824+
792825 break ;
793826 } else {
794- codeStart = LittleEndian::readInt32 (&src[posSection + 0x2C ]);
795- codeEnd = codeStart + LittleEndian::readInt32 (&src[posSection + 0x28 ]);
827+ if (setCodeRange (count, codeStart, codeEnd,
828+ int64 (LittleEndian::readInt32 (&src[posSection + 0x2C ])),
829+ int64 (LittleEndian::readInt32 (&src[posSection + 0x28 ]))) == false )
830+ return false ;
831+
796832 break ;
797833 }
798834 }
0 commit comments