Esempio n. 1
0
        def create_push_for_data(data):
            # expect bytes but silently convert int2bytes
            if isinstance(data, int):
                data = int2bytes(data)

            instr = asm_registry.create_instruction("PUSH%d" % len(data))
            instr.operand_bytes = data
            return instr
Esempio n. 2
0
    def generate(self, length=50):
        if self.fill_arguments:
            length = length // 2
                
        instructions = [asm_registry.create_instruction(opcode=opcode) for opcode in self.random_code_byte_sequence(length)]
        if self.fill_arguments:
            instructions = self._fill_arguments(instructions)

        serialized = ''.join(e.serialize() for e in instructions)     
#        asm = ' '.join(str(e) for e in instructions)
#        print(asm)
        return  "%s%s" % (self.prefix, serialized)
Esempio n. 3
0
    def generate(self, length=None):

        length = self._config_getint("engine.RndCodeInstr.default.length",
                                     50) if length is None else length

        if self.fill_arguments:
            length = length // 2

        self._addresses_seen = set([])  # todo: hacky

        instructions = [
            asm_registry.create_instruction(opcode=opcode)
            for opcode in self.random_code_byte_sequence(length)
        ]
        if self.fill_arguments:
            instructions = self._fill_arguments(instructions)

        serialized = ''.join(e.serialize() for e in instructions)
        #        asm = ' '.join(str(e) for e in instructions)
        #        print(asm)

        return "%s%s" % (self.prefix, serialized)
Esempio n. 4
0
    def _fill_arguments(self, instructions):
        #https://github.com/ethereum/testeth/blob/7cbbb6fed4941420fbae738828fa1339c990e3d3/test/tools/fuzzTesting/fuzzHelper.cpp#L391
        def create_push_for_data(data):
            # expect bytes but silently convert int2bytes
            if isinstance(data, int):
                data = int2bytes(data)

            instr = asm_registry.create_instruction("PUSH%d" % len(data))
            instr.operand_bytes = data
            return instr

        for instr in instructions:
            args_filled = False
            if self.randomPercent() < self._config_getint(
                    "engine.RndCodeInstr.smartCodeProbability.p", 990) / 10:
                # push arguments code
                if instr.name.startswith("PUSH"):
                    instr.randomize_operand()
                elif instr.name.startswith("SWAP"):
                    times = instr.opcode - asm_registry.create_instruction(
                        "SWAP1").opcode + 2
                    for _ in range(times):
                        yield asm_registry.create_instruction(
                            "PUSH%s" %
                            self.randomUniInt(1, 32)).randomize_operand()
                    args_filled = True
                elif instr.name.startswith("DUP"):
                    times = instr.opcode - asm_registry.create_instruction(
                        "DUP1").opcode + 1
                    for _ in range(times):
                        yield asm_registry.create_instruction(
                            "PUSH%s" %
                            self.randomUniInt(1, 32)).randomize_operand()
                    args_filled = True
                elif instr.name.startswith("LOG"):
                    # There can be any number of topics,
                    # followed by memstart and memsize, which must be reasonable
                    yield create_push_for_data(
                        self.randomSmallMemoryLength())  # msize
                    yield create_push_for_data(
                        self.randomSmallMemoryLength())  # mstart
                    args_filled = True
                elif instr.name == "MLOAD":
                    yield create_push_for_data(self.randomSmallMemoryLength())
                    args_filled = True
                elif instr.name == "MSTORE":
                    yield create_push_for_data(
                        self.randomByteSequence(self.randomLength32()))
                    yield create_push_for_data(self.randomSmallMemoryLength())
                    args_filled = True
                elif instr.name == "MSTORE8":
                    #yield create_push_for_data(self.randomByteSequence(self.randomLength32())) # value
                    # We skip pushing the value, and use whatever is already on the stack
                    # Only set a reasonable offset
                    yield create_push_for_data(
                        self.randomSmallMemoryLength())  # offset
                    args_filled = True
                elif instr.name == "RETURNDATACOPY":
                    yield create_push_for_data(self.randomSmallMemoryLength())
                    yield create_push_for_data(self.randomSmallMemoryLength())
                    yield create_push_for_data(self.randomSmallMemoryLength())
                    args_filled = True
                elif instr.name == "EXTCODECOPY":
                    yield create_push_for_data(
                        self.randomSmallMemoryLength())  # length
                    yield create_push_for_data(
                        self.randomMemoryLength())  # codeoffset
                    yield create_push_for_data(
                        self.randomSmallMemoryLength())  # memoffset
                    yield create_push_for_data(
                        self._track_address(
                            RndDestAddress().as_bytes()))  # address
                    args_filled = True
                elif instr.name == "CODECOPY":
                    yield create_push_for_data(
                        self.randomSmallMemoryLength())  # length
                    yield create_push_for_data(
                        self.randomMemoryLength())  # codeoffset
                    yield create_push_for_data(
                        self.randomSmallMemoryLength())  # memoffset
                    args_filled = True
                elif instr.name == "CREATE":
                    yield create_push_for_data(self.randomSmallMemoryLength())
                    yield create_push_for_data(self.randomSmallMemoryLength())
                    yield create_push_for_data(self.randomUniInt(max=255))
                    args_filled = True
                elif instr.name in ("CALL", "CALLCODE"):
                    yield create_push_for_data(self.randomSmallMemoryLength())
                    yield create_push_for_data(self.randomSmallMemoryLength())
                    yield create_push_for_data(self.randomSmallMemoryLength())
                    yield create_push_for_data(self.randomSmallMemoryLength())
                    yield create_push_for_data(
                        self.randomUniInt(max=255))  # value
                    yield create_push_for_data(
                        self._track_address(
                            RndDestAddress().as_bytes()))  # address
                    yield create_push_for_data(self.randomUniInt())  # gas
                    args_filled = True
                elif instr.name in ("STATICCALL", "DELEGATECALL"):
                    yield create_push_for_data(
                        self.randomSmallMemoryLength())  # retsize
                    yield create_push_for_data(
                        self.randomSmallMemoryLength())  # retoffset
                    yield create_push_for_data(
                        self.randomSmallMemoryLength())  # insize
                    yield create_push_for_data(
                        self.randomSmallMemoryLength())  # inoffset
                    yield create_push_for_data(
                        self._track_address(RndDestAddress().as_bytes()))
                    yield create_push_for_data(self.randomUniInt())  # gas
                    args_filled = True
                elif instr.name == "SUICIDE":
                    yield create_push_for_data(
                        self._track_address(RndDestAddress().as_bytes()))
                    args_filled = True
                elif instr.name in ("RETURN", "REVERT"):
                    yield create_push_for_data(self.randomSmallMemoryLength())
                    yield create_push_for_data(self.randomSmallMemoryLength())
                    args_filled = True
                elif instr.name == "CREATE2":
                    # todo: rework
                    yield create_push_for_data(self.randomUniInt())  # salt
                    yield create_push_for_data(self.randomSmallMemoryLength())
                    yield create_push_for_data(self.randomSmallMemoryLength())
                    yield create_push_for_data(
                        self.randomUniInt(max=255))  # value
                    args_filled = True
                elif instr.name == "SSTORE":
                    # use 0-3 for storage keys/vals, to do overwrites and no-change writes.
                    yield create_push_for_data(self.randomUniInt(max=3))
                    yield create_push_for_data(self.randomUniInt(max=3))
                    args_filled = True
                elif instr.name == "SLOAD":
                    # sstore mostly at 0-3, but want some sloads on empty locations
                    yield create_push_for_data(self.randomUniInt(max=8))
                    args_filled = True
                elif instr.name in ["EXTCODEHASH", "EXTCODESIZE"]:
                    # todo: rework
                    yield create_push_for_data(
                        self._track_address(
                            RndDestAddress().as_bytes()))  # address
                    args_filled = True
                elif instr.category in ("bitwise-logic", "comparison"):
                    for _ in instr.args:
                        yield create_push_for_data(self.randomUniInt())
                    args_filled = True

            #  create random args for all other instructions.
            if not args_filled:
                # if args have not been pushed create random args.
                for _ in instr.args:
                    yield create_push_for_data(
                        self.randomByteSequence(self.randomLength32()))

            # finally push instruction
            yield instr