1import angr
2
3######################################
4# select
5######################################
6
7class select(angr.SimProcedure):
8    #pylint:disable=arguments-differ
9
10    def run(self, nfds, readfds, writefds, exceptfds, timeout): # pylint: disable=unused-argument
11        try:
12            nfds_v = self.state.solver.eval_one(nfds)
13            #readfds_v = self.state.solver.eval_one(readfds)
14            writefds_v = self.state.solver.eval_one(writefds)
15            exceptfds_v = self.state.solver.eval_one(exceptfds)
16        except angr.errors.SimSolverError:
17            raise angr.errors.SimProcedureArgumentError("Can't handle symbolic select arguments")
18
19        if writefds_v != 0 or exceptfds_v != 0:
20            raise angr.errors.SimProcedureError("Can't handle write or exception events in select")
21
22        arch_bits = self.arch.bits
23        arch_bytes = self.arch.bytes
24
25        long_array = [ ]
26        long_array_size = ((nfds_v - 1) + arch_bits) // arch_bits
27        for offset in range(0, long_array_size):
28            long = self.state.memory.load(readfds + offset * arch_bytes, arch_bytes, endness=self.arch.memory_endness)
29            long_array.append(long)
30        for i in range(0, nfds_v - 1):
31            # get a bit
32            long_pos = i // arch_bits
33            bit_offset = i % arch_bits
34            bit = long_array[long_pos][bit_offset]
35
36            if bit.symbolic or self.state.solver.eval(bit) == 1:
37                # set this bit to symbolic
38                long_array[long_pos] = long_array[long_pos][arch_bits - 1 : bit_offset + 1].concat(
39                                self.state.solver.BVS('fd_state', 1)).concat(
40                                long_array[long_pos][bit_offset - 1:])
41
42        # write things back
43        for offset in range(0, long_array_size):
44            self.state.memory.store(readfds + offset * arch_bytes, long_array[offset], endness=self.arch.memory_endness)
45
46        retval = self.state.solver.BVV(0, 1).concat(self.state.solver.BVS('select_ret', 31))
47        return retval
48