From cd87544fc72b290002b2dbfbcd4e44674f488905 Mon Sep 17 00:00:00 2001 From: clement rouault Date: Tue, 15 Jun 2021 15:32:23 +0200 Subject: [PATCH] Fix a concurrency error in simple_x86 --- tests/test_simple_x86.py | 34 +++++++++++++++++++++++++++++++ windows/native_exec/simple_x86.py | 13 ++++++++---- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/tests/test_simple_x86.py b/tests/test_simple_x86.py index 3ff8ec9..b3efe23 100644 --- a/tests/test_simple_x86.py +++ b/tests/test_simple_x86.py @@ -261,6 +261,40 @@ def test_x86_instr_multiply(): res += x86.Ret() assert res.get_code() == b"\x90\x90\x90\x90\x90\xc3" +import threading +threads_error = [] + +def test_x86_multithread_target(): + try: + + assert x86.Mov("ECX", "SS").get_code() == b"\x8c\xd1" + assert x86.Mov("SS", "ECX").get_code() == b"\x8e\xd1" + assert x86.Ret().get_code() == b"\xc3" + + res = x86.MultipleInstr() + res += x86.Mov("ECX", "SS") + res += x86.Mov("SS", "ECX") + res += x86.Ret() + assert res.get_code() == b"\x8c\xd1\x8e\xd1\xc3" + except Exception as e: + threads_error.append(e) + raise + return True + +def test_x86_multithread(): + all_threads = [] + for tnb in range(10): + t = threading.Thread(target=test_x86_multithread_target) + all_threads.append(t) + + # import pdb; pdb.set_trace() + for t in all_threads: + t.start() + for t in all_threads: + t.join() + assert not threads_error, "syswow call inconsistent with MultiThreading inconsistent" + + if capstone is None: test_assembler = pytest.mark.skip("Capstone not installed")(test_assembler) diff --git a/windows/native_exec/simple_x86.py b/windows/native_exec/simple_x86.py index 9879a13..0181c88 100644 --- a/windows/native_exec/simple_x86.py +++ b/windows/native_exec/simple_x86.py @@ -28,6 +28,12 @@ class BitArray(object): if size > len(self.array): self.array = ([0] * (size - len(self.array))) + self.array + def copy(self): + new = type(self)(0, "") + new.size = self.size + new.array = list(self.array) + return new + def dump(self): res = [] for i in range(self.size // 8): @@ -283,7 +289,7 @@ RegisterEax = lambda: FixedRegister('EAX') class RawBits(BitArray): def accept_arg(self, args, instr_state): - return (0, self) + return (0, self.copy()) # Immediat value logic @@ -404,8 +410,6 @@ class SegmentSelectorAbsoluteAddr(object): - - class ModRM(object): def __init__(self, sub_modrm, accept_reverse=True, has_direction_bit=True): self.accept_reverse = accept_reverse @@ -438,7 +442,6 @@ class ModRM_REG__REG(object): def match(cls, arg1, arg2): return X86.is_reg(arg1) and X86.is_reg(arg2) - def __init__(self, arg1, arg2, reversed, instr_state): self.mod = BitArray(2, "11") if X86.reg_size(arg1) != X86.reg_size(arg2): @@ -601,6 +604,7 @@ class Instruction(object): encoding = [] def __init__(self, *initial_args): + # print(self, initial_args) for type_encoding in self.encoding: args = list(initial_args) prefix = [] @@ -620,6 +624,7 @@ class Instruction(object): raise ValueError("Cannot encode <{0} {1}>:(".format(type(self).__name__, initial_args)) def get_code(self): + # print(self.value) prefix_opcode = b"".join(chr(p.PREFIX_VALUE) for p in self.prefix) return prefix_opcode + bytes(self.value.dump())