fix(codegen): reject rewrites inside instructions

This commit is contained in:
MrMha 2026-10-11 19:56:00 +04:00
parent a11c8f7f70
commit e5c280fed4
3 changed files with 55 additions and 3 deletions

View File

@ -144,6 +144,22 @@ if(BUILD_TESTING)
target_include_directories(autorun_exit_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/cli/include ${CMAKE_CURRENT_SOURCE_DIR}/io/include ${CMAKE_CURRENT_SOURCE_DIR}/domain/include)
add_test(NAME autorun_exit_status COMMAND autorun_exit_tests)
set_tests_properties(autorun_exit_status PROPERTIES TIMEOUT 20)
add_test_executable(rewrite_boundaries_tests
${CMAKE_CURRENT_SOURCE_DIR}/codegen/tests/RewriteBoundaryTests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/codegen/src/x86/X64InstructionRewriter.cpp
${CMAKE_CURRENT_SOURCE_DIR}/codegen/src/InstructionScanner.cpp
${CMAKE_CURRENT_SOURCE_DIR}/codegen/src/x86/X64InstructionDecoder.cpp
)
target_include_directories(rewrite_boundaries_tests PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/domain/include
${CMAKE_CURRENT_SOURCE_DIR}/relinker/include
${CMAKE_CURRENT_SOURCE_DIR}/elfpatcher/include
${CMAKE_CURRENT_SOURCE_DIR}/codegen/include
${CMAKE_CURRENT_SOURCE_DIR}/io/include
)
add_test(NAME rewrite_boundaries COMMAND rewrite_boundaries_tests)
set_tests_properties(rewrite_boundaries PROPERTIES TIMEOUT 20)
add_test_executable(cli_args_tests
${CMAKE_CURRENT_SOURCE_DIR}/cli/tests/CliArgsTests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/cli/src/CliArgs.cpp

View File

@ -74,6 +74,18 @@ RewriteResult X64InstructionRewriter::Rewrite(
throw CodegenException("Rewrite offset is out of bounds", request.Offset);
}
const auto scanner = MakeInstructionScanner();
const auto matches = scanner->ScanCodeSection(codeSection, 0, codeSection.size());
bool instructionStart = false;
for (const auto& match : matches) {
if (match.Offset == request.Offset) {
instructionStart = true;
break;
}
}
if (!instructionStart)
throw CodegenException("Rewrite offset is not an instruction boundary", request.Offset);
const X64InstructionDecoder decoder;
const std::size_t decodedLength = decoder.Decode(codeSection.data() + offset, codeSection.size() - offset);
@ -90,9 +102,6 @@ RewriteResult X64InstructionRewriter::Rewrite(
rewritten.insert(rewritten.end(), request.NewBytes.begin(), request.NewBytes.end());
rewritten.insert(rewritten.end(), codeSection.begin() + offset + decodedLength, codeSection.end());
const auto scanner = MakeInstructionScanner();
const auto matches = scanner->ScanCodeSection(codeSection, 0, codeSection.size());
std::vector<AddressAdjustment> adjustments;
for (const auto& match : matches) {

View File

@ -0,0 +1,27 @@
#include <codegen/x86/X64InstructionRewriter.hpp>
#include <iostream>
#include <stdexcept>
static void Require(bool ok) { if (!ok) throw std::runtime_error("Invalid rewrite boundary accepted"); }
int main() {
try {
const Codegen::X64InstructionRewriter rewriter;
for (const auto& code : {std::vector<std::uint8_t>{0xB8, 0x90, 0x90, 0x90, 0x90, 0xC3},
std::vector<std::uint8_t>{0x48, 0x8B, 0x05, 0x90, 0x90, 0x90, 0x90, 0xC3},
std::vector<std::uint8_t>{0xE8, 0x90, 0x90, 0x90, 0x90, 0xC3}}) {
const auto original = code;
for (std::size_t offset = 1; offset + 1 < code.size(); ++offset) {
bool rejected = false;
try { (void)rewriter.Rewrite(code, {offset, {0x90}}); }
catch (const std::exception&) { rejected = true; }
Require(rejected && code == original);
}
const auto result = rewriter.Rewrite(code, {0, {0x90}});
Require(result.Bytes == std::vector<std::uint8_t>{0x90, 0xC3});
}
const auto result = rewriter.Rewrite({0x90, 0x90, 0xC3}, {1, {0x90, 0x90}});
Require(result.Bytes == std::vector<std::uint8_t>{0x90, 0x90, 0x90, 0xC3});
std::cout << "18 rewrite boundary cases passed\n";
} catch (const std::exception& error) { std::cerr << error.what() << '\n'; return 1; }
}