fix(codegen): reject rewrites inside instructions
This commit is contained in:
parent
a11c8f7f70
commit
e5c280fed4
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
}
|
||||
Loading…
Reference in New Issue