Skip to content

Commit

Permalink
Fix parsing of unsigned 64-bit constants (Boyan-MILANOV#36)
Browse files Browse the repository at this point in the history
* fix typo in error msg (invald -> invalid)

* replace stoll by stoull: former cannot deal with (unsigned) constants such as 0xffffffffffffffff but instead causes a crash. The implicit assumption here was that large values must be signed values (and should be passed as -1 instead of 0xff..ff). Using stoull fixes this problem and allows the code to work with both unsigned and signed constants

* add il parser for 64 bit and testcases to verify that the code can deal with both 0xffffffffffffffff and -1
  • Loading branch information
mu00d8 authored Jan 9, 2022
1 parent 16f3a82 commit a9cbff2
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 3 deletions.
4 changes: 2 additions & 2 deletions libropium/compiler/il.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ bool _parse_il_cst(Arch& arch, vector<cst_t>& args, string& str, int& idx){
}

try{
cst = std::stoll(s, 0, base);
cst = std::stoull(s, 0, base);
// Check if cst is not too big
if( arch.octets < 8 && (cst >= (ucst_t)((ucst_t)1<<(arch.bits)))){
return false;
Expand Down Expand Up @@ -769,7 +769,7 @@ bool _parse_il_instruction(Arch& arch, ILInstruction* instr, string& str){

ILInstruction::ILInstruction(Arch& arch, string str){
if( !_parse_il_instruction(arch, this, str)){
throw il_exception("Invald instruction string");
throw il_exception("Invalid instruction string");
}
}

Expand Down
40 changes: 39 additions & 1 deletion tests/test_il.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ namespace test{
nb += _assert(instr.type == ILInstructionType::LOAD_CST, "Failed to parse IL Instruction");
nb += _assert(instr.args[PARAM_LOADCST_DST_REG] == X86_EAX, "Failed to parse IL Instruction");
nb += _assert(instr.args[PARAM_LOADCST_SRC_ADDR_OFFSET] == 0xffffffff, "Failed to parse IL Instruction");

// aload_cst
str = " edi ^= [0]";
instr = ILInstruction(arch, str);
Expand Down Expand Up @@ -360,6 +360,43 @@ namespace test{

return nb;
}

unsigned int il_parser64(){
unsigned int nb = 0;
ArchX64 arch;

// parse_il_cst should work with both unsigned and signed constants
string str = " 1000( 0xffffffffffffffff, -1 )";
ILInstruction instr = ILInstruction(arch, str);
nb += _assert(instr.type == ILInstructionType::FUNCTION, "Failed to parse IL Instruction");
nb += _assert(instr.args[PARAM_FUNCTION_ADDR] == 1000, "Failed to parse IL Instruction");
nb += _assert(instr.args[PARAM_FUNCTION_ARGS+0] == (cst_t)0xffffffffffffffff, "Failed to parse IL Instruction");
nb += _assert(instr.args_type[PARAM_FUNCTION_ARGS+0] == IL_FUNC_ARG_CST, "Failed to parse IL Instruction");
nb += _assert(instr.args[PARAM_FUNCTION_ARGS+1] == -1, "Failed to parse IL Instruction");
nb += _assert(instr.args_type[PARAM_FUNCTION_ARGS+1] == IL_FUNC_ARG_CST, "Failed to parse IL Instruction");

str = "rax= [0x7000000000000000]";
instr = ILInstruction(arch, str);
nb += _assert(instr.type == ILInstructionType::LOAD_CST, "Failed to parse IL Instruction");
nb += _assert(instr.args[PARAM_LOADCST_DST_REG] == X64_RAX, "Failed to parse IL Instruction");
nb += _assert(instr.args[PARAM_LOADCST_SRC_ADDR_OFFSET] == (cst_t)0x7000000000000000, "Failed to parse IL Instruction");

// 0xffffffffffffffff == -1
str = "rdx= 0xffffffffffffffff";
instr = ILInstruction(arch, str);
nb += _assert(instr.type == ILInstructionType::MOV_CST, "Failed to parse IL Instruction");
nb += _assert(instr.args[PARAM_MOVCST_DST_REG] == X64_RDX, "Failed to parse IL Instruction");
nb += _assert(instr.args[PARAM_MOVCST_SRC_CST] == -1, "Failed to parse IL Instruction");

// Edge case: -0xffffffffffffffff == -(0xffffffffffffffff) == -(-1) == 1
str = "rcx= -0xffffffffffffffff";
instr = ILInstruction(arch, str);
nb += _assert(instr.type == ILInstructionType::MOV_CST, "Failed to parse IL Instruction");
nb += _assert(instr.args[PARAM_MOVCST_DST_REG] == X64_RCX, "Failed to parse IL Instruction");
nb += _assert(instr.args[PARAM_MOVCST_SRC_CST] == 1, "Failed to parse IL Instruction");

return nb;
}
}
}

Expand All @@ -374,6 +411,7 @@ void test_il(){
// Start testing
cout << bold << "[" << green << "+" << def << bold << "]" << def << std::left << std::setw(34) << " Testing il module... " << std::flush;
total += il_parser();
total += il_parser64();
// Return res
cout << "\t" << total << "/" << total << green << "\t\tOK" << def << endl;
}

0 comments on commit a9cbff2

Please sign in to comment.