angr 9.2.115__py3-none-manylinux2014_aarch64.whl → 9.2.117__py3-none-manylinux2014_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of angr might be problematic. Click here for more details.

Files changed (161) hide show
  1. angr/__init__.py +1 -1
  2. angr/__main__.py +1 -1
  3. angr/analyses/cfg/cfg_emulated.py +4 -4
  4. angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +7 -7
  5. angr/analyses/cfg/indirect_jump_resolvers/mips_elf_fast.py +3 -2
  6. angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +5 -1
  7. angr/analyses/decompiler/structured_codegen/c.py +10 -13
  8. angr/analyses/decompiler/structuring/dream.py +3 -4
  9. angr/analyses/decompiler/structuring/phoenix.py +4 -5
  10. angr/analyses/decompiler/structuring/structurer_base.py +2 -3
  11. angr/analyses/decompiler/structuring/structurer_nodes.py +3 -3
  12. angr/analyses/identifier/functions/free.py +3 -1
  13. angr/analyses/identifier/identify.py +13 -15
  14. angr/analyses/identifier/runner.py +2 -2
  15. angr/analyses/reaching_definitions/dep_graph.py +62 -5
  16. angr/analyses/reaching_definitions/function_handler_library/__init__.py +11 -0
  17. angr/analyses/reaching_definitions/function_handler_library/stdio.py +15 -13
  18. angr/analyses/reaching_definitions/function_handler_library/stdlib.py +17 -11
  19. angr/analyses/reaching_definitions/function_handler_library/string.py +1 -1
  20. angr/analyses/reaching_definitions/function_handler_library/unistd.py +2 -2
  21. angr/analyses/reaching_definitions/rd_state.py +26 -29
  22. angr/analyses/variable_recovery/engine_vex.py +0 -9
  23. angr/analyses/vfg.py +4 -4
  24. angr/calling_conventions.py +4 -2
  25. angr/concretization_strategies/any_named.py +3 -1
  26. angr/concretization_strategies/controlled_data.py +4 -2
  27. angr/concretization_strategies/signed_add.py +3 -1
  28. angr/engines/concrete.py +3 -1
  29. angr/engines/pcode/behavior.py +2 -0
  30. angr/engines/pcode/cc.py +2 -0
  31. angr/engines/pcode/emulate.py +4 -4
  32. angr/engines/pcode/engine.py +3 -7
  33. angr/engines/soot/engine.py +7 -6
  34. angr/engines/soot/expressions/constants.py +6 -5
  35. angr/engines/soot/expressions/newArray.py +3 -1
  36. angr/engines/soot/expressions/newMultiArray.py +3 -1
  37. angr/engines/soot/statements/goto.py +3 -1
  38. angr/engines/soot/statements/if_.py +3 -1
  39. angr/engines/soot/statements/switch.py +3 -1
  40. angr/engines/soot/statements/throw.py +4 -2
  41. angr/engines/soot/values/arrayref.py +5 -5
  42. angr/engines/unicorn.py +8 -7
  43. angr/engines/vex/heavy/concretizers.py +6 -6
  44. angr/engines/vex/heavy/dirty.py +20 -22
  45. angr/engines/vex/heavy/heavy.py +4 -8
  46. angr/exploration_techniques/director.py +1 -1
  47. angr/exploration_techniques/driller_core.py +3 -1
  48. angr/exploration_techniques/tracer.py +2 -1
  49. angr/knowledge_plugins/key_definitions/live_definitions.py +12 -13
  50. angr/procedures/cgc/allocate.py +8 -10
  51. angr/procedures/cgc/deallocate.py +10 -3
  52. angr/procedures/cgc/fdwait.py +15 -13
  53. angr/procedures/cgc/random.py +11 -5
  54. angr/procedures/cgc/receive.py +5 -3
  55. angr/procedures/cgc/transmit.py +5 -4
  56. angr/procedures/glibc/__libc_start_main.py +5 -4
  57. angr/procedures/java_jni/__init__.py +4 -4
  58. angr/procedures/java_jni/array_operations.py +3 -1
  59. angr/procedures/java_lang/string.py +1 -1
  60. angr/procedures/java_util/random.py +3 -1
  61. angr/procedures/libc/access.py +4 -2
  62. angr/procedures/libc/feof.py +4 -3
  63. angr/procedures/libc/fgetc.py +3 -1
  64. angr/procedures/libc/fgets.py +5 -5
  65. angr/procedures/libc/fopen.py +5 -4
  66. angr/procedures/libc/fread.py +4 -3
  67. angr/procedures/libc/fseek.py +4 -3
  68. angr/procedures/libc/getdelim.py +7 -4
  69. angr/procedures/libc/gets.py +4 -2
  70. angr/procedures/libc/memcmp.py +18 -15
  71. angr/procedures/libc/memset.py +9 -7
  72. angr/procedures/libc/puts.py +3 -1
  73. angr/procedures/libc/snprintf.py +4 -2
  74. angr/procedures/libc/sprintf.py +3 -1
  75. angr/procedures/libc/strchr.py +6 -3
  76. angr/procedures/libc/strcmp.py +5 -3
  77. angr/procedures/libc/strlen.py +3 -3
  78. angr/procedures/libc/strncmp.py +28 -28
  79. angr/procedures/libc/strncpy.py +5 -2
  80. angr/procedures/libc/strstr.py +10 -7
  81. angr/procedures/libc/strtol.py +32 -34
  82. angr/procedures/libc/tolower.py +3 -1
  83. angr/procedures/libc/toupper.py +3 -1
  84. angr/procedures/linux_kernel/fstat.py +13 -13
  85. angr/procedures/linux_kernel/fstat64.py +15 -15
  86. angr/procedures/linux_kernel/lseek.py +5 -3
  87. angr/procedures/linux_kernel/sigaction.py +4 -2
  88. angr/procedures/linux_kernel/sigprocmask.py +5 -3
  89. angr/procedures/linux_kernel/tgkill.py +3 -1
  90. angr/procedures/linux_kernel/time.py +7 -4
  91. angr/procedures/msvcr/fmode.py +3 -1
  92. angr/procedures/ntdll/exceptions.py +3 -1
  93. angr/procedures/posix/bzero.py +3 -1
  94. angr/procedures/posix/fdopen.py +6 -4
  95. angr/procedures/posix/fork.py +6 -4
  96. angr/procedures/posix/mmap.py +6 -3
  97. angr/procedures/posix/poll.py +6 -5
  98. angr/procedures/posix/readdir.py +10 -7
  99. angr/procedures/posix/select.py +4 -2
  100. angr/procedures/posix/send.py +4 -3
  101. angr/procedures/posix/sigaction.py +4 -2
  102. angr/procedures/posix/sim_time.py +3 -1
  103. angr/procedures/posix/strcasecmp.py +3 -1
  104. angr/procedures/posix/strtok_r.py +10 -7
  105. angr/procedures/stubs/Redirect.py +3 -1
  106. angr/procedures/stubs/ReturnChar.py +3 -3
  107. angr/procedures/stubs/UserHook.py +3 -1
  108. angr/procedures/stubs/b64_decode.py +3 -1
  109. angr/procedures/stubs/crazy_scanf.py +6 -4
  110. angr/procedures/stubs/format_parser.py +13 -15
  111. angr/procedures/tracer/receive.py +3 -1
  112. angr/procedures/tracer/transmit.py +3 -1
  113. angr/procedures/win32/GetLastInputInfo.py +4 -2
  114. angr/procedures/win32/GetProcessAffinityMask.py +4 -2
  115. angr/procedures/win32/gethostbyname.py +3 -1
  116. angr/procedures/win32/heap.py +3 -1
  117. angr/procedures/win32/local_storage.py +4 -2
  118. angr/procedures/win32/sim_time.py +7 -4
  119. angr/procedures/win_user32/chars.py +4 -2
  120. angr/procedures/win_user32/messagebox.py +3 -1
  121. angr/sim_procedure.py +7 -7
  122. angr/sim_state.py +10 -7
  123. angr/sim_type.py +3 -3
  124. angr/simos/cgc.py +2 -2
  125. angr/simos/simos.py +5 -4
  126. angr/simos/windows.py +5 -5
  127. angr/state_plugins/heap/heap_brk.py +5 -3
  128. angr/state_plugins/heap/heap_ptmalloc.py +5 -4
  129. angr/state_plugins/history.py +7 -5
  130. angr/state_plugins/light_registers.py +2 -2
  131. angr/state_plugins/plugin.py +2 -2
  132. angr/state_plugins/posix.py +28 -26
  133. angr/state_plugins/preconstrainer.py +2 -1
  134. angr/state_plugins/solver.py +11 -27
  135. angr/state_plugins/trace_additions.py +9 -13
  136. angr/state_plugins/uc_manager.py +4 -2
  137. angr/state_plugins/unicorn_engine.py +1 -1
  138. angr/state_plugins/view.py +1 -1
  139. angr/storage/file.py +21 -26
  140. angr/storage/memory_mixins/actions_mixin.py +4 -2
  141. angr/storage/memory_mixins/address_concretization_mixin.py +3 -3
  142. angr/storage/memory_mixins/default_filler_mixin.py +6 -4
  143. angr/storage/memory_mixins/javavm_memory/javavm_memory_mixin.py +7 -5
  144. angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +1 -1
  145. angr/storage/memory_mixins/paged_memory/pages/cooperation.py +2 -1
  146. angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +1 -1
  147. angr/storage/memory_mixins/regioned_memory/region_data.py +3 -1
  148. angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +1 -1
  149. angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +5 -4
  150. angr/storage/memory_mixins/simple_interface_mixin.py +2 -2
  151. angr/storage/memory_mixins/size_resolution_mixin.py +3 -1
  152. angr/storage/memory_mixins/slotted_memory.py +1 -1
  153. angr/storage/memory_mixins/smart_find_mixin.py +2 -2
  154. angr/storage/memory_mixins/symbolic_merger_mixin.py +5 -3
  155. angr/tablespecs.py +3 -3
  156. {angr-9.2.115.dist-info → angr-9.2.117.dist-info}/METADATA +7 -7
  157. {angr-9.2.115.dist-info → angr-9.2.117.dist-info}/RECORD +161 -161
  158. {angr-9.2.115.dist-info → angr-9.2.117.dist-info}/WHEEL +1 -1
  159. {angr-9.2.115.dist-info → angr-9.2.117.dist-info}/LICENSE +0 -0
  160. {angr-9.2.115.dist-info → angr-9.2.117.dist-info}/entry_points.txt +0 -0
  161. {angr-9.2.115.dist-info → angr-9.2.117.dist-info}/top_level.txt +0 -0
angr/__init__.py CHANGED
@@ -1,7 +1,7 @@
1
1
  # pylint: disable=wildcard-import
2
2
  # pylint: disable=wrong-import-position
3
3
 
4
- __version__ = "9.2.115"
4
+ __version__ = "9.2.117"
5
5
 
6
6
  if bytes is str:
7
7
  raise Exception(
angr/__main__.py CHANGED
@@ -42,7 +42,7 @@ def main():
42
42
  "--structurer",
43
43
  help="The structuring algorithm to use for decompilation.",
44
44
  choices=STRUCTURER_CLASSES.keys(),
45
- default=DEFAULT_STRUCTURER,
45
+ default=DEFAULT_STRUCTURER.NAME,
46
46
  )
47
47
 
48
48
  args = parser.parse_args()
@@ -1016,7 +1016,7 @@ class CFGEmulated(ForwardAnalysis, CFGBase): # pylint: disable=abstract-method
1016
1016
  state = self._initial_state.copy()
1017
1017
  state.history.jumpkind = jumpkind
1018
1018
  self._reset_state_mode(state, "fastpath")
1019
- state._ip = state.solver.BVV(ip, self.project.arch.bits)
1019
+ state._ip = claripy.BVV(ip, self.project.arch.bits)
1020
1020
 
1021
1021
  if jumpkind is not None:
1022
1022
  state.history.jumpkind = jumpkind
@@ -1095,7 +1095,7 @@ class CFGEmulated(ForwardAnalysis, CFGBase): # pylint: disable=abstract-method
1095
1095
  f = self._pending_function_hints.pop()
1096
1096
  if f not in analyzed_addrs:
1097
1097
  new_state = self.project.factory.entry_state(mode="fastpath")
1098
- new_state.ip = new_state.solver.BVV(f, self.project.arch.bits)
1098
+ new_state.ip = claripy.BVV(f, self.project.arch.bits)
1099
1099
 
1100
1100
  # TOOD: Specially for MIPS
1101
1101
  if new_state.arch.name in ("MIPS32", "MIPS64"):
@@ -1783,7 +1783,7 @@ class CFGEmulated(ForwardAnalysis, CFGBase): # pylint: disable=abstract-method
1783
1783
  if suc_jumpkind == "Ijk_Ret":
1784
1784
  target_addr = job.call_stack.current_return_target
1785
1785
  if target_addr is not None:
1786
- new_state.ip = new_state.solver.BVV(target_addr, new_state.arch.bits)
1786
+ new_state.ip = claripy.BVV(target_addr, new_state.arch.bits)
1787
1787
 
1788
1788
  if target_addr is None:
1789
1789
  # Unlucky...
@@ -2445,7 +2445,7 @@ class CFGEmulated(ForwardAnalysis, CFGBase): # pylint: disable=abstract-method
2445
2445
  resolved = True
2446
2446
  for t in targets:
2447
2447
  new_ex = suc.copy()
2448
- new_ex.ip = suc.solver.BVV(t, suc.ip.size())
2448
+ new_ex.ip = claripy.BVV(t, suc.ip.size())
2449
2449
  all_successors.append(new_ex)
2450
2450
  else:
2451
2451
  break
@@ -634,7 +634,7 @@ class StoreHook:
634
634
  write_length = len(state.inspect.mem_write_expr)
635
635
  else:
636
636
  write_length = write_length * state.arch.byte_width
637
- state.inspect.mem_write_expr = state.solver.BVS("instrumented_store", write_length)
637
+ state.inspect.mem_write_expr = claripy.BVS("instrumented_store", write_length)
638
638
 
639
639
 
640
640
  class LoadHook:
@@ -648,7 +648,7 @@ class LoadHook:
648
648
  def hook_before(self, state):
649
649
  addr = state.inspect.mem_read_address
650
650
  size = state.solver.eval(state.inspect.mem_read_length)
651
- self._var = state.solver.BVS("instrumented_load", size * 8)
651
+ self._var = claripy.BVS("instrumented_load", size * 8)
652
652
  state.memory.store(addr, self._var, endness=state.arch.memory_endness)
653
653
 
654
654
  def hook_after(self, state):
@@ -662,7 +662,7 @@ class PutHook:
662
662
 
663
663
  @staticmethod
664
664
  def hook(state):
665
- state.inspect.reg_write_expr = state.solver.BVS(
665
+ state.inspect.reg_write_expr = claripy.BVS(
666
666
  "instrumented_put", state.solver.eval(state.inspect.reg_write_length) * 8
667
667
  )
668
668
 
@@ -678,7 +678,7 @@ class RegisterInitializerHook:
678
678
  self.value = value
679
679
 
680
680
  def hook(self, state):
681
- state.registers.store(self.reg_offset, state.solver.BVV(self.value, self.reg_bits))
681
+ state.registers.store(self.reg_offset, claripy.BVV(self.value, self.reg_bits))
682
682
 
683
683
 
684
684
  class BSSHook:
@@ -2106,7 +2106,7 @@ class JumpTableResolver(IndirectJumpResolver):
2106
2106
  read_length = claripy.backends.vsa.convert(read_length).upper_bound
2107
2107
  if read_length > 16:
2108
2108
  return
2109
- new_read_addr = state.solver.BVV(UninitReadMeta.uninit_read_base, state.arch.bits)
2109
+ new_read_addr = claripy.BVV(UninitReadMeta.uninit_read_base, state.arch.bits)
2110
2110
  UninitReadMeta.uninit_read_base += read_length
2111
2111
 
2112
2112
  # replace the expression in registers
@@ -2238,7 +2238,7 @@ class JumpTableResolver(IndirectJumpResolver):
2238
2238
  # blx r0
2239
2239
  # It's not a jump table, but we resolve it anyway
2240
2240
  jump_target_addr = load_stmt.data.addr.con.value
2241
- return state.solver.BVV(jump_target_addr, state.arch.bits)
2241
+ return claripy.BVV(jump_target_addr, state.arch.bits)
2242
2242
  elif isinstance(load_stmt, pyvex.IRStmt.LoadG):
2243
2243
  if type(load_stmt.addr) is pyvex.IRExpr.RdTmp:
2244
2244
  load_addr_tmp = load_stmt.addr.tmp
@@ -2254,7 +2254,7 @@ class JumpTableResolver(IndirectJumpResolver):
2254
2254
  # Note that this block has two branches: One goes to 45450, the other one goes to whatever the original
2255
2255
  # value of R3 is. Some intensive data-flow analysis is required in this case.
2256
2256
  jump_target_addr = load_stmt.addr.con.value
2257
- return state.solver.BVV(jump_target_addr, state.arch.bits)
2257
+ return claripy.BVV(jump_target_addr, state.arch.bits)
2258
2258
  else:
2259
2259
  raise TypeError("Unsupported address loading statement type %s." % type(load_stmt))
2260
2260
 
@@ -2,8 +2,9 @@
2
2
  from typing import TYPE_CHECKING
3
3
  import logging
4
4
 
5
- import pyvex
6
5
  import archinfo
6
+ import claripy
7
+ import pyvex
7
8
 
8
9
 
9
10
  from .... import options, BP_BEFORE
@@ -45,7 +46,7 @@ class OverwriteTmpValueCallback:
45
46
  self.gp_value = gp_value
46
47
 
47
48
  def overwrite_tmp_value(self, state):
48
- state.inspect.tmp_write_expr = state.solver.BVV(self.gp_value, state.arch.bits)
49
+ state.inspect.tmp_write_expr = claripy.BVV(self.gp_value, state.arch.bits)
49
50
 
50
51
 
51
52
  class MipsElfFastResolver(IndirectJumpResolver):
@@ -182,7 +182,11 @@ class StackCanarySimplifier(OptimizationPass):
182
182
 
183
183
  while True:
184
184
  traversed.add(block_addr)
185
- first_block = next(self._get_blocks(block_addr))
185
+ try:
186
+ first_block = next(self._get_blocks(block_addr))
187
+ except StopIteration:
188
+ break
189
+
186
190
  if first_block is None:
187
191
  break
188
192
 
@@ -1,7 +1,7 @@
1
1
  # pylint:disable=missing-class-docstring,too-many-boolean-expressions,unused-argument,no-self-use
2
2
  from typing import Optional, Any, TYPE_CHECKING
3
3
  from collections.abc import Callable
4
- from collections import defaultdict
4
+ from collections import defaultdict, Counter
5
5
  import logging
6
6
  import struct
7
7
 
@@ -491,19 +491,16 @@ class CFunction(CConstruct): # pylint:disable=abstract-method
491
491
  else:
492
492
  name = str(variable)
493
493
 
494
- # sort by number of occurrences, with a preference of non-basic types
494
+ # sort by the following:
495
+ # * if it's a a non-basic type
496
+ # * the number of occurrences
497
+ # * the repr of the type itself
495
498
  # TODO: The type selection should actually happen during variable unification
496
499
  vartypes = [x[1] for x in cvar_and_vartypes]
497
- nonprimitive_vartypes = [
498
- vt for vt in vartypes if not isinstance(vt, (SimTypeChar, SimTypeInt, SimTypeFloat))
499
- ]
500
- vartypes = list(dict.fromkeys(sorted(vartypes, key=vartypes.count, reverse=True)))
501
- if nonprimitive_vartypes:
502
- nonprimitive_vartypes = list(
503
- dict.fromkeys(sorted(nonprimitive_vartypes, key=nonprimitive_vartypes.count, reverse=True))
504
- )
505
- vartypes.remove(nonprimitive_vartypes[0])
506
- vartypes.insert(0, nonprimitive_vartypes[0])
500
+ count = Counter(vartypes)
501
+ vartypes = sorted(
502
+ count.copy(), key=lambda x: (isinstance(x, (SimTypeChar, SimTypeInt, SimTypeFloat)), count[x], repr(x))
503
+ )
507
504
 
508
505
  for i, var_type in enumerate(vartypes):
509
506
  if i == 0:
@@ -2177,8 +2174,8 @@ class CConstant(CExpression):
2177
2174
  v = refval.content.decode("utf-8")
2178
2175
  else:
2179
2176
  # it's a string
2180
- assert isinstance(v, str)
2181
2177
  v = refval
2178
+ assert isinstance(v, str)
2182
2179
  yield CConstant.str_to_c_str(v), self
2183
2180
  elif isinstance(self._type, SimTypePointer) and isinstance(self._type.pts_to, SimTypeWideChar):
2184
2181
  refval = self.reference_values[self._type]
@@ -1,6 +1,5 @@
1
1
  # pylint:disable=multiple-statements,line-too-long,consider-using-enumerate
2
2
  from typing import Optional, Any, TYPE_CHECKING
3
- from collections import OrderedDict as ODict
4
3
  import logging
5
4
  from collections import defaultdict, OrderedDict
6
5
 
@@ -661,7 +660,7 @@ class DreamStructurer(StructurerBase):
661
660
  i,
662
661
  node,
663
662
  cmp_expr,
664
- cases: ODict,
663
+ cases: OrderedDict,
665
664
  node_default,
666
665
  addr,
667
666
  addr2nodes,
@@ -909,7 +908,7 @@ class DreamStructurer(StructurerBase):
909
908
  head_node_idx: int,
910
909
  node_b_addr: int,
911
910
  addr2nodes: dict[int, set[CodeNode]],
912
- ) -> tuple[ODict, Any, Any]:
911
+ ) -> tuple[OrderedDict, Any, Any]:
913
912
  """
914
913
  Discover all cases for the switch-case structure and build the switch-cases dict.
915
914
 
@@ -922,7 +921,7 @@ class DreamStructurer(StructurerBase):
922
921
  :return: A tuple of (dict of cases, the default node if exists, nodes to remove).
923
922
  """
924
923
 
925
- cases: ODict[int | tuple[int, ...], SequenceNode] = OrderedDict()
924
+ cases: OrderedDict[int | tuple[int, ...], SequenceNode] = OrderedDict()
926
925
  to_remove = set()
927
926
  node_default = addr2nodes.get(node_b_addr, None)
928
927
  if node_default is not None:
@@ -1,7 +1,6 @@
1
1
  # pylint:disable=line-too-long,import-outside-toplevel,import-error,multiple-statements,too-many-boolean-expressions
2
2
  from typing import Any, DefaultDict, Optional, TYPE_CHECKING
3
- from collections import OrderedDict as ODict
4
- from collections import defaultdict
3
+ from collections import defaultdict, OrderedDict
5
4
  from enum import Enum
6
5
  import logging
7
6
 
@@ -1308,8 +1307,8 @@ class PhoenixStructurer(StructurerBase):
1308
1307
  node_b_addr,
1309
1308
  graph,
1310
1309
  full_graph,
1311
- ) -> tuple[ODict, Any, set[Any]]:
1312
- cases: ODict[int | tuple[int], SequenceNode] = ODict()
1310
+ ) -> tuple[OrderedDict, Any, set[Any]]:
1311
+ cases: OrderedDict[int | tuple[int], SequenceNode] = OrderedDict()
1313
1312
  to_remove = set()
1314
1313
 
1315
1314
  # it is possible that the default node gets duplicated by other analyses and creates a default node (addr.a)
@@ -1418,7 +1417,7 @@ class PhoenixStructurer(StructurerBase):
1418
1417
  self,
1419
1418
  head,
1420
1419
  cmp_expr,
1421
- cases: ODict,
1420
+ cases: OrderedDict,
1422
1421
  node_default_addr: int,
1423
1422
  node_default,
1424
1423
  addr,
@@ -1,6 +1,5 @@
1
1
  # pylint:disable=unused-argument
2
2
  from typing import Optional, Any, TYPE_CHECKING
3
- from collections import OrderedDict as ODict
4
3
  from collections import defaultdict, OrderedDict
5
4
  import logging
6
5
 
@@ -739,8 +738,8 @@ class StructurerBase(Analysis):
739
738
  #
740
739
 
741
740
  def _reorganize_switch_cases(
742
- self, cases: ODict[int | tuple[int, ...], SequenceNode]
743
- ) -> ODict[int | tuple[int, ...], SequenceNode]:
741
+ self, cases: OrderedDict[int | tuple[int, ...], SequenceNode]
742
+ ) -> OrderedDict[int | tuple[int, ...], SequenceNode]:
744
743
  new_cases = OrderedDict()
745
744
 
746
745
  caseid2gotoaddrs = {}
@@ -1,6 +1,6 @@
1
1
  # pylint:disable=missing-class-docstring
2
2
  from typing import Any
3
- from collections import OrderedDict as ODict
3
+ from collections import OrderedDict
4
4
 
5
5
  import claripy
6
6
  import ailment
@@ -358,9 +358,9 @@ class SwitchCaseNode(BaseNode):
358
358
  "addr",
359
359
  )
360
360
 
361
- def __init__(self, switch_expr, cases: ODict[int | tuple[int, ...], SequenceNode], default_node, addr=None):
361
+ def __init__(self, switch_expr, cases: OrderedDict[int | tuple[int, ...], SequenceNode], default_node, addr=None):
362
362
  self.switch_expr = switch_expr
363
- self.cases: ODict[int | tuple[int, ...], SequenceNode] = cases
363
+ self.cases: OrderedDict[int | tuple[int, ...], SequenceNode] = cases
364
364
  self.default_node = default_node
365
365
  self.addr = addr
366
366
 
@@ -1,5 +1,7 @@
1
1
  import logging
2
2
 
3
+ import claripy
4
+
3
5
  from ..func import Func, TestData
4
6
  from ..errors import IdentifierException
5
7
 
@@ -52,7 +54,7 @@ class free(Func):
52
54
  test_input = [malloc_vals[-1]]
53
55
  test_output = [None]
54
56
  return_val = None
55
- state.memory.store(malloc_vals[-1], state.solver.BVS("some_data", 0x80 * 8))
57
+ state.memory.store(malloc_vals[-1], claripy.BVS("some_data", 0x80 * 8))
56
58
  free_test = TestData(test_input, test_output, return_val, max_steps)
57
59
  state = runner.get_out_state(func, free_test, initial_state=state)
58
60
  if state is None:
@@ -1,10 +1,10 @@
1
+ import logging
1
2
  from collections import defaultdict
2
3
  from itertools import chain
3
- import logging
4
-
5
- from networkx import NetworkXError
6
4
 
5
+ import claripy
7
6
  from cle.backends.cgc import CGC
7
+ from networkx import NetworkXError
8
8
 
9
9
  from .errors import IdentifierException
10
10
  from .functions import Functions
@@ -75,9 +75,7 @@ class Identifier(Analysis):
75
75
 
76
76
  self.base_symbolic_state = self.make_symbolic_state(self.project, self._reg_list)
77
77
  self.base_symbolic_state.options.discard(options.SUPPORT_FLOATING_POINT)
78
- self.base_symbolic_state.regs.bp = self.base_symbolic_state.solver.BVS(
79
- "sreg_" + "ebp" + "-", self.project.arch.bits
80
- )
78
+ self.base_symbolic_state.regs.bp = claripy.BVS("sreg_" + "ebp" + "-", self.project.arch.bits)
81
79
 
82
80
  for f in self._cfg.functions.values():
83
81
  if f.is_syscall:
@@ -308,7 +306,7 @@ class Identifier(Analysis):
308
306
 
309
307
  func_info = self.func_info[self.block_to_func[addr_trace[0]]]
310
308
  for i in range(func_info.frame_size // self.project.arch.bytes + 5):
311
- s.stack_push(s.solver.BVS("var_" + hex(i), self.project.arch.bits))
309
+ s.stack_push(claripy.BVS("var_" + hex(i), self.project.arch.bits))
312
310
 
313
311
  if func_info.bp_based:
314
312
  s.regs.bp = s.regs.sp + func_info.bp_sp_diff
@@ -322,7 +320,7 @@ class Identifier(Analysis):
322
320
  for ss in simgr.active:
323
321
  # todo could write symbolic data to pointers passed to functions
324
322
  if ss.history.jumpkind == "Ijk_Call":
325
- ss.regs.eax = ss.solver.BVS("unconstrained_ret_%#x" % ss.addr, ss.arch.bits)
323
+ ss.regs.eax = claripy.BVS("unconstrained_ret_%#x" % ss.addr, ss.arch.bits)
326
324
  ss.regs.ip = ss.stack_pop()
327
325
  ss.history.jumpkind = "Ijk_Ret"
328
326
  if ss.addr == addr_trace[0]:
@@ -333,7 +331,7 @@ class Identifier(Analysis):
333
331
  if len(simgr.unconstrained) > 0:
334
332
  s = simgr.unconstrained[0]
335
333
  if s.history.jumpkind == "Ijk_Call":
336
- s.regs.eax = s.solver.BVS("unconstrained_ret", s.arch.bits)
334
+ s.regs.eax = claripy.BVS("unconstrained_ret", s.arch.bits)
337
335
  s.regs.ip = s.stack_pop()
338
336
  s.history.jumpkind = "Ijk_Ret"
339
337
  s.regs.ip = addr_trace[0]
@@ -437,7 +435,7 @@ class Identifier(Analysis):
437
435
  state = input_state.copy()
438
436
  # overwrite all registers
439
437
  for reg in reg_list:
440
- state.registers.store(reg, state.solver.BVS("sreg_" + reg + "-", project.arch.bits, explicit_name=True))
438
+ state.registers.store(reg, claripy.BVS("sreg_" + reg + "-", project.arch.bits, explicit_name=True))
441
439
  # restore sp
442
440
  state.regs.sp = input_state.regs.sp
443
441
  # restore bp
@@ -600,11 +598,11 @@ class Identifier(Analysis):
600
598
  for bl_addr in func.block_addrs:
601
599
  all_addrs.update(set(self._cfg.model.get_any_node(bl_addr).instruction_addrs))
602
600
 
603
- sp = main_state.solver.BVS("sym_sp", self.project.arch.bits, explicit_name=True)
601
+ sp = claripy.BVS("sym_sp", self.project.arch.bits, explicit_name=True)
604
602
  main_state.regs.sp = sp
605
603
  bp = None
606
604
  if bp_based:
607
- bp = main_state.solver.BVS("sym_bp", self.project.arch.bits, explicit_name=True)
605
+ bp = claripy.BVS("sym_bp", self.project.arch.bits, explicit_name=True)
608
606
  main_state.regs.bp = bp
609
607
 
610
608
  stack_vars = set()
@@ -731,7 +729,7 @@ class Identifier(Analysis):
731
729
  def _sets_ebp_from_esp(self, state, addr):
732
730
  state = state.copy()
733
731
  state.regs.ip = addr
734
- state.regs.sp = state.solver.BVS("sym_sp", 32, explicit_name=True)
732
+ state.regs.sp = claripy.BVS("sym_sp", 32, explicit_name=True)
735
733
  succ = self.project.factory.successors(state).all_successors[0]
736
734
 
737
735
  diff = state.regs.sp - succ.regs.bp
@@ -818,7 +816,7 @@ class Identifier(Analysis):
818
816
  options.TRACK_CONSTRAINT_ACTIONS,
819
817
  }
820
818
  )
821
- symbolic_stack = initial_state.solver.BVS("symbolic_stack", project.arch.bits * stack_length)
819
+ symbolic_stack = claripy.BVS("symbolic_stack", project.arch.bits * stack_length)
822
820
  initial_state.memory.store(initial_state.regs.sp, symbolic_stack)
823
821
  if initial_state.arch.bp_offset != initial_state.arch.sp_offset:
824
822
  initial_state.regs.bp = initial_state.regs.sp + 20 * initial_state.arch.bytes
@@ -835,7 +833,7 @@ class Identifier(Analysis):
835
833
  symbolic_state = input_state.copy()
836
834
  # overwrite all registers
837
835
  for reg in reg_list:
838
- symbolic_state.registers.store(reg, symbolic_state.solver.BVS("sreg_" + reg + "-", project.arch.bits))
836
+ symbolic_state.registers.store(reg, claripy.BVS("sreg_" + reg + "-", project.arch.bits))
839
837
  # restore sp
840
838
  symbolic_state.regs.sp = input_state.regs.sp
841
839
  # restore bp
@@ -52,7 +52,7 @@ class Runner:
52
52
  entry_state = self.project.factory.entry_state(add_options=add_options, remove_options=remove_options)
53
53
 
54
54
  # map the CGC flag page
55
- fake_flag_data = entry_state.solver.BVV(FLAG_DATA)
55
+ fake_flag_data = claripy.BVV(FLAG_DATA)
56
56
  entry_state.memory.store(0x4347C000, fake_flag_data)
57
57
  # map the place where I put arguments
58
58
  entry_state.memory.map_region(0x2000, 0x10000, 7)
@@ -176,7 +176,7 @@ class Runner:
176
176
  buf = state.solver.eval(state.regs.ebx)
177
177
  for i in range(count):
178
178
  a = random.randint(0, 255)
179
- state.memory.store(buf + i, state.solver.BVV(a, 8))
179
+ state.memory.store(buf + i, claripy.BVV(a, 8))
180
180
 
181
181
  def get_base_call_state(self, function, test_data, initial_state=None, concrete_rand=False):
182
182
  curr_buf_loc = 0x2000
@@ -213,6 +213,68 @@ class DepGraph:
213
213
 
214
214
  self.graph.add_edge(memory_location_definition, definition)
215
215
 
216
+ @overload
217
+ def find_definitions(
218
+ self,
219
+ *,
220
+ kind: type[A],
221
+ **kwargs: Any,
222
+ ) -> list[Definition[A]]: ...
223
+
224
+ @overload
225
+ def find_definitions(
226
+ self,
227
+ *,
228
+ kind: Literal[AtomKind.REGISTER] = AtomKind.REGISTER,
229
+ **kwargs: Any,
230
+ ) -> list[Definition[Register]]: ...
231
+
232
+ @overload
233
+ def find_definitions(
234
+ self,
235
+ *,
236
+ kind: Literal[AtomKind.MEMORY] = AtomKind.MEMORY,
237
+ **kwargs: Any,
238
+ ) -> list[Definition[MemoryLocation]]: ...
239
+
240
+ @overload
241
+ def find_definitions(
242
+ self,
243
+ *,
244
+ kind: Literal[AtomKind.TMP] = AtomKind.TMP,
245
+ **kwargs: Any,
246
+ ) -> list[Definition[Tmp]]: ...
247
+
248
+ @overload
249
+ def find_definitions(
250
+ self,
251
+ *,
252
+ kind: Literal[AtomKind.CONSTANT] = AtomKind.CONSTANT,
253
+ **kwargs: Any,
254
+ ) -> list[Definition[ConstantSrc]]: ...
255
+
256
+ @overload
257
+ def find_definitions(
258
+ self,
259
+ *,
260
+ kind: Literal[AtomKind.GUARD] = AtomKind.GUARD,
261
+ **kwargs: Any,
262
+ ) -> list[Definition[GuardUse]]: ...
263
+
264
+ @overload
265
+ def find_definitions(
266
+ self,
267
+ *,
268
+ reg_name: int | str = ...,
269
+ **kwargs: Any,
270
+ ) -> list[Definition[Register]]: ...
271
+
272
+ @overload
273
+ def find_definitions(self, *, stack_offset: int = ..., **kwargs: Any) -> list[Definition[MemoryLocation]]: ...
274
+
275
+ @overload
276
+ def find_definitions(self, *, const_val: int = ..., **kwargs: Any) -> list[Definition[ConstantSrc]]: ...
277
+
216
278
  def find_definitions(self, **kwargs) -> list[Definition]:
217
279
  """
218
280
  Filter the definitions present in the graph based on various criteria.
@@ -299,11 +361,6 @@ class DepGraph:
299
361
  self, starts: Definition[Atom] | Iterable[Definition[Atom]], *, const_val: int = ..., **kwargs: Any
300
362
  ) -> list[Definition[ConstantSrc]]: ...
301
363
 
302
- @overload
303
- def find_all_predecessors(
304
- self, starts: Definition[Atom] | Iterable[Definition[Atom]], **kwargs: Any
305
- ) -> list[Definition[Atom]]: ...
306
-
307
364
  def find_all_predecessors(self, starts, **kwargs):
308
365
  """
309
366
  Filter the ancestors of the given start node or nodes that match various criteria.
@@ -0,0 +1,11 @@
1
+ from .stdlib import LibcStdlibHandlers, EnvironAtom, SystemAtom, ExecveAtom
2
+ from .stdio import LibcStdioHandlers, StdoutAtom, StdinAtom
3
+ from .unistd import LibcUnistdHandlers
4
+ from .string import LibcStringHandlers
5
+
6
+
7
+ class LibcHandlers(LibcStdlibHandlers, LibcStdioHandlers, LibcUnistdHandlers, LibcStringHandlers):
8
+ pass
9
+
10
+
11
+ __all__ = ["EnvironAtom", "SystemAtom", "ExecveAtom", "StdoutAtom", "StdinAtom", "LibcHandlers"]
@@ -19,10 +19,10 @@ _l = logging.getLogger(__name__)
19
19
 
20
20
 
21
21
  class StdoutAtom(Atom):
22
- def __init__(self, sink: str):
22
+ def __init__(self, sink: str, size: int | None):
23
23
  self.nonce = random.randint(0, 999999999999)
24
24
  self.sink = sink
25
- super().__init__(1)
25
+ super().__init__(size if size is not None else 1)
26
26
 
27
27
  def _identity(self):
28
28
  return (self.nonce,)
@@ -32,10 +32,10 @@ class StdoutAtom(Atom):
32
32
 
33
33
 
34
34
  class StdinAtom(Atom):
35
- def __init__(self, source: str):
35
+ def __init__(self, source: str, size: int | None):
36
36
  self.nonce = random.randint(0, 999999999999)
37
37
  self.source = source
38
- super().__init__(1)
38
+ super().__init__(size if size is not None else 1)
39
39
 
40
40
  def _identity(self):
41
41
  return (self.nonce,)
@@ -83,19 +83,19 @@ class LibcStdioHandlers(FunctionHandler):
83
83
  @FunctionCallDataUnwrapped.decorate
84
84
  def handle_impl_printf(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
85
85
  result, source_atoms = handle_printf(state, data, 0)
86
- dst_atoms = StdoutAtom("printf")
86
+ dst_atoms = StdoutAtom("printf", len(result) if result is not None else None)
87
87
  data.depends(dst_atoms, source_atoms, value=result)
88
88
 
89
89
  @FunctionCallDataUnwrapped.decorate
90
90
  def handle_impl_dprintf(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
91
91
  result, source_atoms = handle_printf(state, data, 1)
92
- dst_atoms = StdoutAtom("dprintf")
92
+ dst_atoms = StdoutAtom("dprintf", len(result) if result is not None else None)
93
93
  data.depends(dst_atoms, source_atoms, value=result)
94
94
 
95
95
  @FunctionCallDataUnwrapped.decorate
96
96
  def handle_impl_fprintf(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
97
97
  result, source_atoms = handle_printf(state, data, 1)
98
- dst_atoms = StdoutAtom("fprintf")
98
+ dst_atoms = StdoutAtom("fprintf", len(result) if result is not None else None)
99
99
  data.depends(dst_atoms, source_atoms, value=result)
100
100
 
101
101
  @FunctionCallDataUnwrapped.decorate
@@ -108,6 +108,8 @@ class LibcStdioHandlers(FunctionHandler):
108
108
  def handle_impl_snprintf(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
109
109
  result, source_atoms = handle_printf(state, data, 2)
110
110
  size = state.get_concrete_value(data.args_atoms[1]) or 2
111
+ if result is not None:
112
+ size = min(size, len(result) // 8)
111
113
  dst_atoms = state.deref(data.args_atoms[0], size=size)
112
114
  data.depends(dst_atoms, source_atoms, value=result)
113
115
 
@@ -126,7 +128,7 @@ class LibcStdioHandlers(FunctionHandler):
126
128
 
127
129
  @FunctionCallDataUnwrapped.decorate
128
130
  def handle_impl_scanf(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
129
- handle_scanf(state, data, 0, {StdinAtom("scanf")})
131
+ handle_scanf(state, data, 0, {StdinAtom("scanf", None)})
130
132
 
131
133
  handle_impl___isoc99_scanf = handle_impl_scanf
132
134
 
@@ -140,13 +142,13 @@ class LibcStdioHandlers(FunctionHandler):
140
142
  def handle_impl_fgets(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
141
143
  size = state.get_concrete_value(data.args_atoms[1]) or 2
142
144
  dst_atom = state.deref(data.args_atoms[0], size)
143
- input_value = claripy.BVS("weh", 8).concat(claripy.BVV(0, 8))
144
- data.depends(dst_atom, StdinAtom("fgets"), value=input_value)
145
+ input_value = claripy.BVS("weh", (size - 1) * 8).concat(claripy.BVV(0, 8))
146
+ data.depends(dst_atom, StdinAtom("fgets", size), value=input_value)
145
147
  data.depends(data.ret_atoms, data.args_atoms[0])
146
148
 
147
149
  @FunctionCallDataUnwrapped.decorate
148
150
  def handle_impl_fgetc(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
149
- data.depends(data.ret_atoms, StdinAtom(data.function.name))
151
+ data.depends(data.ret_atoms, StdinAtom(data.function.name, 1))
150
152
 
151
153
  handle_impl_getchar = handle_impl_getc = handle_impl_fgetc
152
154
 
@@ -155,14 +157,14 @@ class LibcStdioHandlers(FunctionHandler):
155
157
  size = state.get_concrete_value(data.args_atoms[1]) or 1
156
158
  nmemb = state.get_concrete_value(data.args_atoms[1]) or 2
157
159
  dst_atom = state.deref(data.args_atoms[0], size * nmemb)
158
- data.depends(dst_atom, StdinAtom("fread"))
160
+ data.depends(dst_atom, StdinAtom("fread", size * nmemb))
159
161
 
160
162
  @FunctionCallDataUnwrapped.decorate
161
163
  def handle_impl_fwrite(self, state: ReachingDefinitionsState, data: FunctionCallDataUnwrapped):
162
164
  size = state.get_concrete_value(data.args_atoms[1]) or 1
163
165
  nmemb = state.get_concrete_value(data.args_atoms[1]) or 2
164
166
  src_atom = state.deref(data.args_atoms[0], size * nmemb)
165
- data.depends(StdoutAtom("fwrite"), src_atom, value=state.get_values(src_atom))
167
+ data.depends(StdoutAtom("fwrite", size * nmemb), src_atom, value=state.get_values(src_atom))
166
168
 
167
169
 
168
170
  def handle_printf(