From a9cbff211c1794e19d71aab97a664abb5eb4c362 Mon Sep 17 00:00:00 2001 From: Moritz Schloegel <59735936+mu00d8@users.noreply.github.com> Date: Sun, 9 Jan 2022 17:23:45 +0100 Subject: [PATCH] Fix parsing of unsigned 64-bit constants (#36) * 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 --- libropium/compiler/il.cpp | 4 ++-- tests/test_il.cpp | 40 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/libropium/compiler/il.cpp b/libropium/compiler/il.cpp index 1cc6957..525a396 100644 --- a/libropium/compiler/il.cpp +++ b/libropium/compiler/il.cpp @@ -58,7 +58,7 @@ bool _parse_il_cst(Arch& arch, vector& 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; @@ -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"); } } diff --git a/tests/test_il.cpp b/tests/test_il.cpp index 9deeaf9..9c92aa8 100644 --- a/tests/test_il.cpp +++ b/tests/test_il.cpp @@ -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); @@ -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; + } } } @@ -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; }