diff --git a/core/relinker/codegen/src/Amd64OnlyConverter.cpp b/core/relinker/codegen/src/Amd64OnlyConverter.cpp index 7e1966132..f92c5edc9 100644 --- a/core/relinker/codegen/src/Amd64OnlyConverter.cpp +++ b/core/relinker/codegen/src/Amd64OnlyConverter.cpp @@ -296,10 +296,10 @@ void Amd64OnlyConverter::_convertSegment( std::uint64_t completed, std::uint64_t total ) const { + if (ph.Offset > fileBytes.size() || ph.FileSize > fileBytes.size() - ph.Offset) + throw CodegenException("Code segment exceeds the file", ph.Offset); const auto segOffset = static_cast(ph.Offset); const auto segSize = static_cast(ph.FileSize); - if (segOffset > fileBytes.size() || segSize > fileBytes.size() - segOffset) - throw CodegenException("Code segment exceeds the file", ph.Offset); std::vector seg( fileBytes.begin() + static_cast(segOffset), @@ -318,9 +318,9 @@ void Amd64OnlyConverter::_convertSegment( if (substitution.has_value()) pending.push_back({index, match, std::move(*substitution)}); } - if (progress) progress(completed + 2 * segSize, total); + if (progress) progress(completed + std::uint64_t{2} * segSize, total); if (pending.empty()) { - if (progress) progress(completed + 3 * segSize, total); + if (progress) progress(completed + std::uint64_t{3} * segSize, total); return; } @@ -337,7 +337,7 @@ void Amd64OnlyConverter::_convertSegment( std::size_t processed = 0; for (const auto& item : pending) { - if (progress && processed != 0 && processed % 256 == 0) progress(completed + 2 * segSize + item.Instruction.Offset, total); + if (progress && processed != 0 && processed % 256 == 0) progress(completed + std::uint64_t{2} * segSize + item.Instruction.Offset, total); ++processed; if (consumed.contains(item.Index)) continue; @@ -439,7 +439,7 @@ void Amd64OnlyConverter::_convertSegment( if (seg.size() != segSize) throw CodegenException("Code segment size changed during Intel conversion", ph.Offset); std::copy(seg.begin(), seg.end(), fileBytes.begin() + static_cast(segOffset)); - if (progress) progress(completed + 3 * segSize, total); + if (progress) progress(completed + std::uint64_t{3} * segSize, total); } ConvertResult Amd64OnlyConverter::Convert( diff --git a/core/relinker/codegen/src/InstructionScanner.cpp b/core/relinker/codegen/src/InstructionScanner.cpp index 3797a2b09..3cd662a59 100644 --- a/core/relinker/codegen/src/InstructionScanner.cpp +++ b/core/relinker/codegen/src/InstructionScanner.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include namespace Codegen { @@ -17,14 +18,16 @@ private: }; std::vector InstructionScanner::ScanCodeSection(const std::vector& codeSection, const Domain::FileByteOffset codeSectionOffset, const Domain::FileByteOffset codeSectionSize) const { - const std::size_t limit = std::min(codeSection.size(), static_cast(codeSectionSize)); + if (codeSectionSize > codeSection.size()) throw CodegenException("Code section exceeds the input buffer", codeSectionOffset); + if (codeSectionSize > std::numeric_limits::max() - codeSectionOffset) throw CodegenException("Code section offset overflow", codeSectionOffset); + const auto limit = static_cast(codeSectionSize); const X64InstructionDecoder decoder; std::vector matches; std::size_t i = 0; if (progress) progress(0, limit); - std::size_t nextReport = 65536; + std::size_t lastReport = 0; while (i < limit) { const std::uint8_t* cursor = codeSection.data() + i; const std::size_t available = limit - i; @@ -40,9 +43,9 @@ std::vector InstructionScanner::ScanCodeSection(const std::vec matches.push_back({codeSectionOffset + i, length}); i += length; - if (progress && i >= nextReport) { + if (progress && i - lastReport >= 65536) { progress(i, limit); - nextReport = i + 65536; + lastReport = i; } } diff --git a/core/relinker/relinker/src/analysis/SyscallScanner.cpp b/core/relinker/relinker/src/analysis/SyscallScanner.cpp index dccd9816a..128ededb0 100644 --- a/core/relinker/relinker/src/analysis/SyscallScanner.cpp +++ b/core/relinker/relinker/src/analysis/SyscallScanner.cpp @@ -162,7 +162,8 @@ private: }; std::vector SyscallScanner::ScanCodeSectionForSyscalls(const std::vector& codeSection, const FileByteOffset codeSectionOffset, const FileByteOffset codeSectionSize, std::string_view input) { - const std::size_t limit = std::min(codeSection.size(), static_cast(codeSectionSize)); + if (codeSectionSize > codeSection.size()) throw RelinkerException("Code section exceeds the input buffer", codeSectionOffset); + const auto limit = static_cast(codeSectionSize); const auto scanner = Codegen::MakeInstructionScanner([&](auto completed, auto total) { progress.Report({Domain::ProgressStage::Decode, std::string(input), completed, total}); }); const auto matches = scanner->ScanCodeSection(codeSection, codeSectionOffset, codeSectionSize); diff --git a/core/relinker/relinker/tests/ConversionTests.cpp b/core/relinker/relinker/tests/ConversionTests.cpp index d80f012c5..a1d3cd4b9 100644 --- a/core/relinker/relinker/tests/ConversionTests.cpp +++ b/core/relinker/relinker/tests/ConversionTests.cpp @@ -125,6 +125,7 @@ void scanning() { previous = event.Completed; } require(previous == progress.Events.back().Total, "Instruction conversion progress did not finish"); + reject([&] { scanner->ScanCodeSectionForSyscalls(code, 0, (std::uint64_t{1} << 32) + code.size()); }); code[70000] = 0x0f; code[70001] = 0x05; progress.Events.clear();