We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Avoiding Infinite Loops with loopseer technique
Hello,

I'm trying to run some code which I know is just a loop running infinitely but I do want to exit this loop (hard coded limit) after it iterated 10 times.
I thought loopseer suppose to do just that but it doesn't seems to stop after 10 iterations but keep going non stop.

My example code:
```
void loop_forever(int a) {
        int i;
        for(i=0;;i++) {
                printf("Test infinite loop");
        }
}
```

Example usage:
```
p = angr.Project(loop_forever, load_options={"auto_load_libs": False})
cfg = p.analyses.CFGFast(normalize = True)
state = p.factory.call_state(addr=0x10438) # 0x10438 = loop_forever function
simgr = p.factory.simulation_manager(state)
simgr.use_technique(angr.exploration_techniques.LoopSeer(cfg=cfg, bound=10))
while len(simgr.active) != 0:
    simgr.step()
    print simgr.active
```

The binary (elf, 32bit arm) can be download here: https://ufile.io/9nym2

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `angr/exploration_techniques/loop_seer.py`
Content:
```
1 import logging
2 
3 from . import ExplorationTechnique
4 from ..analyses.loopfinder import Loop
5 from ..knowledge_base import KnowledgeBase
6 from ..knowledge_plugins.functions import Function
7 
8 
9 l = logging.getLogger("angr.exploration_techniques.loop_seer")
10 
11 
12 class LoopSeer(ExplorationTechnique):
13     """
14     This exploration technique monitors exploration and maintains all
15     loop-related data (well, currently it is just the loop trip counts, but feel
16     free to add something else).
17     """
18 
19     def __init__(self, cfg=None, functions=None, loops=None, bound=None, bound_reached=None, discard_stash='spinning'):
20         """
21         :param cfg:             Normalized CFG is required.
22         :param functions:       Function(s) containing the loop(s) to be analyzed.
23         :param loops:           Loop(s) to be analyzed.
24         :param bound:           Limit the number of iteration a loop may be executed.
25         :param bound_reached:   If provided, should be a function that takes a SimulationManager and returns
26                                 a SimulationManager. Will be called when loop execution reach the given bound.
27                                 Default to moving states that exceed the loop limit to a discard stash.
28         :param discard_stash:   Name of the stash containing states exceeding the loop limit.
29         """
30 
31         super(LoopSeer, self).__init__()
32         self.cfg = cfg
33         self.functions = functions
34         self.bound = bound
35         self.bound_reached = bound_reached
36         self.discard_stash = discard_stash
37 
38         self.loops = {}
39 
40         if type(loops) is Loop:
41             loops = [loops]
42 
43         if type(loops) in (list, tuple) and all(type(l) is Loop for l in loops):
44             for loop in loops:
45                 self.loops[loop.entry_edges[0][0].addr] = loop
46 
47         elif loops is not None:
48             raise TypeError('What type of loop is it?')
49 
50     def setup(self, simgr):
51         if self.cfg is None:
52             cfg_kb = KnowledgeBase(self.project, self.project.loader.main_object)
53             self.cfg = self.project.analyses.CFGFast(kb=cfg_kb, normalize=True)
54         elif not self.cfg.normalized:
55             l.warning("LoopSeer uses normalized CFG. Recomputing the CFG...")
56             self.cfg.normalize()
57 
58         if type(self.functions) is str:
59             func = [self.cfg.kb.functions.function(name=self.functions)]
60 
61         elif type(self.functions) is int:
62             func = [self.cfg.kb.functions.function(addr=self.functions)]
63 
64         elif type(self.functions) is Function:
65             func = [self.functions]
66 
67         elif type(self.functions) in (list, tuple):
68             func = []
69             for f in self.functions:
70                 if type(f) is str:
71                     func.append(self.cfg.kb.functions.function(name=f))
72 
73                 elif type(f) is int:
74                     func.append(self.cfg.kb.functions.function(addr=f))
75 
76                 elif type(f) is Function:
77                     func.append(f)
78 
79                 else:
80                     raise TypeError("What type of function is it?")
81         elif self.functions is None:
82             func = None
83 
84         else:
85             raise TypeError("What type of function is it?")
86 
87         if not self.loops or func is not None:
88             loop_finder = self.project.analyses.LoopFinder(kb=self.cfg.kb, normalize=True, functions=func)
89 
90             for loop in loop_finder.loops:
91                 entry = loop.entry_edges[0][0]
92                 self.loops[entry.addr] = loop
93 
94     def step(self, simgr, stash=None, **kwargs):
95         kwargs['successor_func'] = self.normalized_step
96 
97         simgr.step(stash=stash, **kwargs)
98 
99         for state in simgr.stashes[stash]:
100             # Processing a currently running loop
101             if state.loop_data.current_loop:
102                 loop = state.loop_data.current_loop[-1][0]
103                 header = loop.entry.addr
104 
105                 if state.addr == header:
106                     state.loop_data.trip_counts[state.addr][-1] += 1
107 
108                 elif state.addr in state.loop_data.current_loop[-1][1]:
109                     # This is for unoptimized while/for loops.
110                     #
111                     # 0x10812: movs r3, #0          -> this block dominates the loop
112                     # 0x10814: str  r3, [r7, #20]
113                     # 0x10816: b    0x10868
114                     # 0x10818: movs r3, #0          -> the real loop body starts here
115                     # ...
116                     # 0x10868: ldr  r3, [r7, #20]   -> the loop header is executed the first time without executing the loop body
117                     # 0x1086a: cmp  r3, #3
118                     # 0x1086c: ble  0x10818
119 
120                     back_edge_src = loop.continue_edges[0][0].addr
121                     back_edge_dst = loop.continue_edges[0][1].addr
122                     block = self.project.factory.block(back_edge_src)
123                     if back_edge_src != back_edge_dst and back_edge_dst in block.instruction_addrs:
124                         state.loop_data.trip_counts[header][-1] -= 1
125 
126                     state.loop_data.current_loop.pop()
127 
128                 if self.bound is not None:
129                     if state.loop_data.trip_counts[header][-1] >= self.bound:
130                         if self.bound_reached is not None:
131                             simgr = self.bound_reached(simgr)
132                         else:
133                             simgr.stashes[stash].remove(state)
134                             simgr.stashes[self.discard_stash].append(state)
135 
136                 l.debug("%s trip counts %s", state, state.loop_data.trip_counts)
137 
138             # Loop entry detected. This test is put here because in case of
139             # nested loops, we want to handle the outer loop before proceeding
140             # the inner loop.
141             if state.addr in self.loops:
142                 loop = self.loops[state.addr]
143                 header = loop.entry.addr
144                 exits = [e[1].addr for e in loop.break_edges]
145 
146                 state.loop_data.trip_counts[header].append(0)
147                 state.loop_data.current_loop.append((loop, exits))
148 
149         return simgr
150 
151     def normalized_step(self, state):
152         node = self.cfg.get_any_node(state.addr)
153         return state.step(num_inst=len(node.instruction_addrs) if node is not None else None)
154
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/angr/exploration_techniques/loop_seer.py b/angr/exploration_techniques/loop_seer.py
--- a/angr/exploration_techniques/loop_seer.py
+++ b/angr/exploration_techniques/loop_seer.py
@@ -91,11 +91,9 @@
                 entry = loop.entry_edges[0][0]
                 self.loops[entry.addr] = loop
 
-    def step(self, simgr, stash=None, **kwargs):
+    def step(self, simgr, stash='active', **kwargs):
         kwargs['successor_func'] = self.normalized_step
 
-        simgr.step(stash=stash, **kwargs)
-
         for state in simgr.stashes[stash]:
             # Processing a currently running loop
             if state.loop_data.current_loop:
@@ -126,7 +124,7 @@
                     state.loop_data.current_loop.pop()
 
                 if self.bound is not None:
-                    if state.loop_data.trip_counts[header][-1] >= self.bound:
+                    if state.loop_data.trip_counts[header][-1] > self.bound:
                         if self.bound_reached is not None:
                             simgr = self.bound_reached(simgr)
                         else:
@@ -146,6 +144,8 @@
                 state.loop_data.trip_counts[header].append(0)
                 state.loop_data.current_loop.append((loop, exits))
 
+        simgr.step(stash=stash, **kwargs)
+
         return simgr
 
     def normalized_step(self, state):

{"golden_diff": "diff --git a/angr/exploration_techniques/loop_seer.py b/angr/exploration_techniques/loop_seer.py\n--- a/angr/exploration_techniques/loop_seer.py\n+++ b/angr/exploration_techniques/loop_seer.py\n@@ -91,11 +91,9 @@\n                 entry = loop.entry_edges[0][0]\n                 self.loops[entry.addr] = loop\n \n-    def step(self, simgr, stash=None, **kwargs):\n+    def step(self, simgr, stash='active', **kwargs):\n         kwargs['successor_func'] = self.normalized_step\n \n-        simgr.step(stash=stash, **kwargs)\n-\n         for state in simgr.stashes[stash]:\n             # Processing a currently running loop\n             if state.loop_data.current_loop:\n@@ -126,7 +124,7 @@\n                     state.loop_data.current_loop.pop()\n \n                 if self.bound is not None:\n-                    if state.loop_data.trip_counts[header][-1] >= self.bound:\n+                    if state.loop_data.trip_counts[header][-1] > self.bound:\n                         if self.bound_reached is not None:\n                             simgr = self.bound_reached(simgr)\n                         else:\n@@ -146,6 +144,8 @@\n                 state.loop_data.trip_counts[header].append(0)\n                 state.loop_data.current_loop.append((loop, exits))\n \n+        simgr.step(stash=stash, **kwargs)\n+\n         return simgr\n \n     def normalized_step(self, state):\n", "issue": "Avoiding Infinite Loops with loopseer technique\nHello,\r\n\r\nI'm trying to run some code which I know is just a loop running infinitely but I do want to exit this loop (hard coded limit) after it iterated 10 times.\r\nI thought loopseer suppose to do just that but it doesn't seems to stop after 10 iterations but keep going non stop.\r\n\r\nMy example code:\r\n```\r\nvoid loop_forever(int a) {\r\n        int i;\r\n        for(i=0;;i++) {\r\n                printf(\"Test infinite loop\");\r\n        }\r\n}\r\n```\r\n\r\nExample usage:\r\n```\r\np = angr.Project(loop_forever, load_options={\"auto_load_libs\": False})\r\ncfg = p.analyses.CFGFast(normalize = True)\r\nstate = p.factory.call_state(addr=0x10438) # 0x10438 = loop_forever function\r\nsimgr = p.factory.simulation_manager(state)\r\nsimgr.use_technique(angr.exploration_techniques.LoopSeer(cfg=cfg, bound=10))\r\nwhile len(simgr.active) != 0:\r\n    simgr.step()\r\n    print simgr.active\r\n```\r\n\r\nThe binary (elf, 32bit arm) can be download here: https://ufile.io/9nym2\n", "before_files": [{"content": "import logging\n\nfrom . import ExplorationTechnique\nfrom ..analyses.loopfinder import Loop\nfrom ..knowledge_base import KnowledgeBase\nfrom ..knowledge_plugins.functions import Function\n\n\nl = logging.getLogger(\"angr.exploration_techniques.loop_seer\")\n\n\nclass LoopSeer(ExplorationTechnique):\n    \"\"\"\n    This exploration technique monitors exploration and maintains all\n    loop-related data (well, currently it is just the loop trip counts, but feel\n    free to add something else).\n    \"\"\"\n\n    def __init__(self, cfg=None, functions=None, loops=None, bound=None, bound_reached=None, discard_stash='spinning'):\n        \"\"\"\n        :param cfg:             Normalized CFG is required.\n        :param functions:       Function(s) containing the loop(s) to be analyzed.\n        :param loops:           Loop(s) to be analyzed.\n        :param bound:           Limit the number of iteration a loop may be executed.\n        :param bound_reached:   If provided, should be a function that takes a SimulationManager and returns\n                                a SimulationManager. Will be called when loop execution reach the given bound.\n                                Default to moving states that exceed the loop limit to a discard stash.\n        :param discard_stash:   Name of the stash containing states exceeding the loop limit.\n        \"\"\"\n\n        super(LoopSeer, self).__init__()\n        self.cfg = cfg\n        self.functions = functions\n        self.bound = bound\n        self.bound_reached = bound_reached\n        self.discard_stash = discard_stash\n\n        self.loops = {}\n\n        if type(loops) is Loop:\n            loops = [loops]\n\n        if type(loops) in (list, tuple) and all(type(l) is Loop for l in loops):\n            for loop in loops:\n                self.loops[loop.entry_edges[0][0].addr] = loop\n\n        elif loops is not None:\n            raise TypeError('What type of loop is it?')\n\n    def setup(self, simgr):\n        if self.cfg is None:\n            cfg_kb = KnowledgeBase(self.project, self.project.loader.main_object)\n            self.cfg = self.project.analyses.CFGFast(kb=cfg_kb, normalize=True)\n        elif not self.cfg.normalized:\n            l.warning(\"LoopSeer uses normalized CFG. Recomputing the CFG...\")\n            self.cfg.normalize()\n\n        if type(self.functions) is str:\n            func = [self.cfg.kb.functions.function(name=self.functions)]\n\n        elif type(self.functions) is int:\n            func = [self.cfg.kb.functions.function(addr=self.functions)]\n\n        elif type(self.functions) is Function:\n            func = [self.functions]\n\n        elif type(self.functions) in (list, tuple):\n            func = []\n            for f in self.functions:\n                if type(f) is str:\n                    func.append(self.cfg.kb.functions.function(name=f))\n\n                elif type(f) is int:\n                    func.append(self.cfg.kb.functions.function(addr=f))\n\n                elif type(f) is Function:\n                    func.append(f)\n\n                else:\n                    raise TypeError(\"What type of function is it?\")\n        elif self.functions is None:\n            func = None\n\n        else:\n            raise TypeError(\"What type of function is it?\")\n\n        if not self.loops or func is not None:\n            loop_finder = self.project.analyses.LoopFinder(kb=self.cfg.kb, normalize=True, functions=func)\n\n            for loop in loop_finder.loops:\n                entry = loop.entry_edges[0][0]\n                self.loops[entry.addr] = loop\n\n    def step(self, simgr, stash=None, **kwargs):\n        kwargs['successor_func'] = self.normalized_step\n\n        simgr.step(stash=stash, **kwargs)\n\n        for state in simgr.stashes[stash]:\n            # Processing a currently running loop\n            if state.loop_data.current_loop:\n                loop = state.loop_data.current_loop[-1][0]\n                header = loop.entry.addr\n\n                if state.addr == header:\n                    state.loop_data.trip_counts[state.addr][-1] += 1\n\n                elif state.addr in state.loop_data.current_loop[-1][1]:\n                    # This is for unoptimized while/for loops.\n                    #\n                    # 0x10812: movs r3, #0          -> this block dominates the loop\n                    # 0x10814: str  r3, [r7, #20]\n                    # 0x10816: b    0x10868\n                    # 0x10818: movs r3, #0          -> the real loop body starts here\n                    # ...\n                    # 0x10868: ldr  r3, [r7, #20]   -> the loop header is executed the first time without executing the loop body\n                    # 0x1086a: cmp  r3, #3\n                    # 0x1086c: ble  0x10818\n\n                    back_edge_src = loop.continue_edges[0][0].addr\n                    back_edge_dst = loop.continue_edges[0][1].addr\n                    block = self.project.factory.block(back_edge_src)\n                    if back_edge_src != back_edge_dst and back_edge_dst in block.instruction_addrs:\n                        state.loop_data.trip_counts[header][-1] -= 1\n\n                    state.loop_data.current_loop.pop()\n\n                if self.bound is not None:\n                    if state.loop_data.trip_counts[header][-1] >= self.bound:\n                        if self.bound_reached is not None:\n                            simgr = self.bound_reached(simgr)\n                        else:\n                            simgr.stashes[stash].remove(state)\n                            simgr.stashes[self.discard_stash].append(state)\n\n                l.debug(\"%s trip counts %s\", state, state.loop_data.trip_counts)\n\n            # Loop entry detected. This test is put here because in case of\n            # nested loops, we want to handle the outer loop before proceeding\n            # the inner loop.\n            if state.addr in self.loops:\n                loop = self.loops[state.addr]\n                header = loop.entry.addr\n                exits = [e[1].addr for e in loop.break_edges]\n\n                state.loop_data.trip_counts[header].append(0)\n                state.loop_data.current_loop.append((loop, exits))\n\n        return simgr\n\n    def normalized_step(self, state):\n        node = self.cfg.get_any_node(state.addr)\n        return state.step(num_inst=len(node.instruction_addrs) if node is not None else None)\n", "path": "angr/exploration_techniques/loop_seer.py"}], "after_files": [{"content": "import logging\n\nfrom . import ExplorationTechnique\nfrom ..analyses.loopfinder import Loop\nfrom ..knowledge_base import KnowledgeBase\nfrom ..knowledge_plugins.functions import Function\n\n\nl = logging.getLogger(\"angr.exploration_techniques.loop_seer\")\n\n\nclass LoopSeer(ExplorationTechnique):\n    \"\"\"\n    This exploration technique monitors exploration and maintains all\n    loop-related data (well, currently it is just the loop trip counts, but feel\n    free to add something else).\n    \"\"\"\n\n    def __init__(self, cfg=None, functions=None, loops=None, bound=None, bound_reached=None, discard_stash='spinning'):\n        \"\"\"\n        :param cfg:             Normalized CFG is required.\n        :param functions:       Function(s) containing the loop(s) to be analyzed.\n        :param loops:           Loop(s) to be analyzed.\n        :param bound:           Limit the number of iteration a loop may be executed.\n        :param bound_reached:   If provided, should be a function that takes a SimulationManager and returns\n                                a SimulationManager. Will be called when loop execution reach the given bound.\n                                Default to moving states that exceed the loop limit to a discard stash.\n        :param discard_stash:   Name of the stash containing states exceeding the loop limit.\n        \"\"\"\n\n        super(LoopSeer, self).__init__()\n        self.cfg = cfg\n        self.functions = functions\n        self.bound = bound\n        self.bound_reached = bound_reached\n        self.discard_stash = discard_stash\n\n        self.loops = {}\n\n        if type(loops) is Loop:\n            loops = [loops]\n\n        if type(loops) in (list, tuple) and all(type(l) is Loop for l in loops):\n            for loop in loops:\n                self.loops[loop.entry_edges[0][0].addr] = loop\n\n        elif loops is not None:\n            raise TypeError('What type of loop is it?')\n\n    def setup(self, simgr):\n        if self.cfg is None:\n            cfg_kb = KnowledgeBase(self.project, self.project.loader.main_object)\n            self.cfg = self.project.analyses.CFGFast(kb=cfg_kb, normalize=True)\n        elif not self.cfg.normalized:\n            l.warning(\"LoopSeer uses normalized CFG. Recomputing the CFG...\")\n            self.cfg.normalize()\n\n        if type(self.functions) is str:\n            func = [self.cfg.kb.functions.function(name=self.functions)]\n\n        elif type(self.functions) is int:\n            func = [self.cfg.kb.functions.function(addr=self.functions)]\n\n        elif type(self.functions) is Function:\n            func = [self.functions]\n\n        elif type(self.functions) in (list, tuple):\n            func = []\n            for f in self.functions:\n                if type(f) is str:\n                    func.append(self.cfg.kb.functions.function(name=f))\n\n                elif type(f) is int:\n                    func.append(self.cfg.kb.functions.function(addr=f))\n\n                elif type(f) is Function:\n                    func.append(f)\n\n                else:\n                    raise TypeError(\"What type of function is it?\")\n        elif self.functions is None:\n            func = None\n\n        else:\n            raise TypeError(\"What type of function is it?\")\n\n        if not self.loops or func is not None:\n            loop_finder = self.project.analyses.LoopFinder(kb=self.cfg.kb, normalize=True, functions=func)\n\n            for loop in loop_finder.loops:\n                entry = loop.entry_edges[0][0]\n                self.loops[entry.addr] = loop\n\n    def step(self, simgr, stash='active', **kwargs):\n        kwargs['successor_func'] = self.normalized_step\n\n        for state in simgr.stashes[stash]:\n            # Processing a currently running loop\n            if state.loop_data.current_loop:\n                loop = state.loop_data.current_loop[-1][0]\n                header = loop.entry.addr\n\n                if state.addr == header:\n                    state.loop_data.trip_counts[state.addr][-1] += 1\n\n                elif state.addr in state.loop_data.current_loop[-1][1]:\n                    # This is for unoptimized while/for loops.\n                    #\n                    # 0x10812: movs r3, #0          -> this block dominates the loop\n                    # 0x10814: str  r3, [r7, #20]\n                    # 0x10816: b    0x10868\n                    # 0x10818: movs r3, #0          -> the real loop body starts here\n                    # ...\n                    # 0x10868: ldr  r3, [r7, #20]   -> the loop header is executed the first time without executing the loop body\n                    # 0x1086a: cmp  r3, #3\n                    # 0x1086c: ble  0x10818\n\n                    back_edge_src = loop.continue_edges[0][0].addr\n                    back_edge_dst = loop.continue_edges[0][1].addr\n                    block = self.project.factory.block(back_edge_src)\n                    if back_edge_src != back_edge_dst and back_edge_dst in block.instruction_addrs:\n                        state.loop_data.trip_counts[header][-1] -= 1\n\n                    state.loop_data.current_loop.pop()\n\n                if self.bound is not None:\n                    if state.loop_data.trip_counts[header][-1] > self.bound:\n                        if self.bound_reached is not None:\n                            simgr = self.bound_reached(simgr)\n                        else:\n                            simgr.stashes[stash].remove(state)\n                            simgr.stashes[self.discard_stash].append(state)\n\n                l.debug(\"%s trip counts %s\", state, state.loop_data.trip_counts)\n\n            # Loop entry detected. This test is put here because in case of\n            # nested loops, we want to handle the outer loop before proceeding\n            # the inner loop.\n            if state.addr in self.loops:\n                loop = self.loops[state.addr]\n                header = loop.entry.addr\n                exits = [e[1].addr for e in loop.break_edges]\n\n                state.loop_data.trip_counts[header].append(0)\n                state.loop_data.current_loop.append((loop, exits))\n\n        simgr.step(stash=stash, **kwargs)\n\n        return simgr\n\n    def normalized_step(self, state):\n        node = self.cfg.get_any_node(state.addr)\n        return state.step(num_inst=len(node.instruction_addrs) if node is not None else None)\n", "path": "angr/exploration_techniques/loop_seer.py"}]}