Commit graph

28 commits

Author SHA1 Message Date
Ati Priya
36587c513a
FunctionParser: Serialize Function._call_sites. (#6613)
* FunctionParser: Serialize Function._call_sites.

serialize stores the transition graph but not Function._call_sites, and
parse_from_cmsg never repopulated it, so functions loaded back from LMDB
(SpillingFunctionDict eviction, angrdb) returned nothing from
get_call_sites(), get_call_target(), and get_call_return().

_call_sites cannot be rebuilt from transition graph edges. Store the
mapping in a new repeated CallSite field on the Function message and
restore it in parse_from_cmsg.

* lint

* Fix pyright errors in FunctionParser.

* Fix pyright error in LMDB function manager test.
2026-07-14 17:15:50 -07:00
Fish
79ec25dc24
FunctionParser: convert previous_names protobuf field to a plain list. (#6584) 2026-07-07 14:21:32 -07:00
Kevin Phoenix
f939c5b88c
Enable ruff isort rule (#6452)
* Enable ruff isort rule

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-06-02 14:48:07 -07:00
Brian Caswell
e79d473426
CFGFast: iterate func.block_addrs for drop_bad_functions cleanup (works for spilled funcs) (#6419)
* cfg_fast: iterate func.block_addrs for bad-func cleanup (works for spilled funcs)

CFGFast.drop_bad_functions's per-block cleanup iterated func.blocks,
which is empty for any bad function loaded via meta_only=True (e.g.
because it was spilled to LMDB by SpillingFunctionDict at drop
time). The loop was silently a no-op for those functions: the
function was removed from kb.functions but its CFG nodes survived
and its bytes stayed classified as 'code' in _seg_list, leaving the
model in a state that depended on LRU cache timing.

Fix: iterate func.block_addrs (populated for both cached and spilled
funcs) and look up block sizes from the CFG model via cfg_node.size.
No extra LMDB I/O; same logic for cached and spilled funcs.

Adds tests/knowledge_plugins/functions/test_function_meta_only_blocks_iterator.py
documenting the meta_only contract that this fix accounts for, plus
an end-to-end check that the cleanup completes on a meta-only-loaded
function.

Fixes #6418

* test_function_meta_only_blocks_iterator: cast cn.addr/size to int for pyright

* test_function_meta_only_blocks_iterator: assert isinstance cn.addr int for pyright

* cfg_fast: use block_addrs_set (not block_addrs) for drop_bad_functions cleanup

Function.block_addrs returns self._local_blocks.keys() which is empty
in meta-only mode. The accessor that returns the populated set on
spilled funcs is Function.block_addrs_set (returns _local_block_addrs).
2026-05-20 02:52:13 -07:00
Brian Caswell
d52c51d60b
function_parser: derive fake_return is_outside from cmsg.blocks membership (defense-in-depth for #6414) (#6417)
* function_parser: derive fake_return outside flag from cmsg.blocks

parse_from_cmessage's call-edge handler called
  obj._call_to(..., return_to_outside=fake_ret_edge is None)
which only checked whether a matching fake_return edge exists, not
whether its destination was external at save time. _call_to then
called _register_node(is_local=True, ret_node) and added the
destination to _local_block_addrs even when it was serialized as an
external_block.

This is a defense-in-depth follow-up to #6416. With that fix landed,
no newly-saved record should contain a fake_return edge with
is_outside=False whose dst is in cmsg.external_blocks. But:
  * legacy LMDB records written before #6416 still have this shape
  * other call sites (notably _add_fakeret_to(confirmed=None)) can
    create the same in-memory inconsistency, which then makes the
    parser inflate the block set on every roundtrip

Fix: derive return_to_outside / to_outside from cmsg.blocks
membership (the authoritative 'was local at save' signal) rather
than from the edge attribute. The same logic applies to the
subsequent obj._fakeret_to call, which previously used the edge
attribute directly.

Adds tests/knowledge_plugins/functions/test_function_parser_fakeret.py
which round-trips a function with the inconsistent edge shape and
asserts _local_block_addrs is preserved.

* test_function_parser_fakeret: assert func is not None for pyright

* test_function_parser_fakeret: drop __package__ override
2026-05-20 02:49:54 -07:00
Brian Caswell
3c2d7f47da
CFGFast: use Function._remove_fakeret (mark dirty) instead of direct transition_graph.remove_edge (#6416)
* cfg_fast: route fake_return cleanup through Function._remove_fakeret

CFGFast._post_analysis's fake_return cleanup loop called
`f.transition_graph.remove_edge(*edge)` directly, bypassing the
@dirty_func-decorated Function._remove_fakeret API. The dirty flag was
never set after the mutation, so on SpillingFunctionDict the next
eviction was clean (no LMDB write) and the cleanup was silently
reverted on the next parse_from_cmessage rebuild.

Symptom: angr-serialize output on PE binaries large enough to hit
cache_limit=1000 functions is non-deterministic — function counts
depend on which functions happen to be cached vs spilled at
drop_bad_functions time, because the cleanup either does or doesn't
survive the LMDB round-trip per function.

Fix: replace the direct graph mutation with the existing
Function._remove_fakeret call. This is symmetric with the
`f._confirm_fakeret(src, dst)` call a few lines above, which already
goes through the Function API.

Adds tests/knowledge_plugins/functions/test_function_post_analysis_dirty.py
to lock in the post-mutation dirty flag.

Fixes #6414

* test_function_post_analysis_dirty: assert func is not None for pyright

* test_function_post_analysis_dirty: drop __package__ override

* test_function_post_analysis_dirty: drop serialize/parse round-trip, set _dirty=False directly
2026-05-20 02:48:10 -07:00
Fish
5ee75140ff
Dev: Switch from black to ruff format. (#6097)
* Dev: Switch from black to ruff format.

* Reformat all the files.
2026-02-05 14:29:21 -07:00
Fish
e13adc02cd
Function.prototype: Automatically set arg names when missing. (#6050)
* Function.prototype: Automatically set arg names when missing.

* Support setting None to Function.prototype.
2026-01-26 06:04:57 -05:00
pre-commit-ci[bot]
563fb5f862
[pre-commit.ci] pre-commit autoupdate (#6025)
* [pre-commit.ci] pre-commit autoupdate

updates:
- [github.com/astral-sh/ruff-pre-commit: v0.14.11 → v0.14.13](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.11...v0.14.13)
- [github.com/psf/black-pre-commit-mirror: 25.12.0 → 26.1.0](https://github.com/psf/black-pre-commit-mirror/compare/25.12.0...26.1.0)

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-01-19 13:37:06 -07:00
Fish
a31f3df8f7
FunctionManager: Spill to external storage. (#5976)
* FunctionManager: Spill to external storage.

* Remove atexit registration. Reduce map size.

* Introduce FuncNode in function graphs; Fix multiple issues with SpillingFunctionDict.

* Implement Function.dirty.

* A bit more optimization.

* FunctionManager loads only meta data for functions when graphs are not accessed; Save .info for functions.

* Only load meta data for Functions in more places.

* Remove FunctionManager.block_map because it's never really used.

* Retire blockaddr_to_function and replace it with blockaddr_to_funcaddr.

* More optimizations and fixes.

* More refactor and fixes.

* More optimizations.

* Fix the bug in lmdb spilling after raising MapFullError.

* Introduce RuntimeDb in KB. Migrate SpillingFunctionsDict to use RuntimeDb.

* Prioritize the basedir of the main executable for the runtime db path.

* Cache non-returning function addrs, unknown-returning function addrs, and function block count in FunctionManager.

* Bug fixes.

* Fix a bug in FunctionParser.

* CFGBase.make_functions: Copy over function metadata when creating functions in the first place.

* Update MockFunctionManager.

* Type check codenode.py and fix an RDA test case.

* Fix serialization tests; Introduce KnowledgeBasePlugin.set_kb(); SpillingFunctionDict now derives from UserDict; Fix KB.name stored in KB._plugins; Fix FunctionDict.__setstate__ swapping Function objects and function addresses.

* Update FactCollector to support FuncNode.

* FunctionInfo: Update Function.dirty and perform type checks on keys and values.

* Make function cache limit configurable.

* Adjust FunctionInfo type check.

* More fixes.

* More updates to account for FuncNode in function graphs.

* Update a test case.

* Fix another test case (do not use the size of FuncNodes).

* Fix Reassembler.

* CFGBase.make_functions: Add a missing insertion to _updated_nonreturning_functions.

* Update FunctionManager.rebuild_callgraph.

* FunctionParser: Call destinations must be FuncNodes.

* Serialize Function.is_default_name.

* Minor fixes.

* Fix CFunctionCall._is_target_ambiguous.

* Mark evicted Function instances as evicted.

* HashLookupAPIDeobfuscator: Take a list of function addresses instead of Function instances as arg.

* CC_NAMES: Fix the bug of missing SimCCCdecl.

* FunctionParser: Fix missing syscall function nodes.

* HookNode: Take a SimProcedure instance instead of the class as the sim_procedure argument.

* FunctionParser: Consider return-type edges when deserializing.

* SimTypeCppFunction: Fix to_json() serialization crash.

* FunctionParser: Fix missing return sites.

* Function.is_{syscall,simprocedure,alignment,plt} settings should mark the function dirty.

* RDA: Do not create blocks for FuncNodes or HookNodes.

* Update a test case.

* Fix issues with SimCppClass.to_json.

* HookNode: Fix HookNode.__eq__.

* Fix SootFunction.

* Lint function_manager.py.

* Lint and type check.

* More docs; Spill Function.ran_cca.

* RuntimeDb: Support specifying base dir using an environment variable.

* Lint and fix test cases.
2026-01-12 19:58:18 -07:00
Fish
e7cf358a85
Remove pickle from Function.prototype serialization. (#5787)
* Remove pickle from Function.prototype serialization.

* Add a test case.

* Type check.
2025-11-12 20:12:48 -07:00
Audrey Dutcher
7cf133c99d
chore: Make SIM_LIBRARIES a dict of list of lib instead of a dict of lib (#5336)
* chore: Make SIM_LIBRARIES a dict of list of lib instead of a dict of lib

* lint

* Revert "Temporarily disabling a line in test_decompiling_4846..."

This reverts commit eafdbf857a.

* remove stray line
2025-03-24 15:01:56 -07:00
Fish
816108fd00
FunctionManager: Better support for renamed functions. (#5007)
* support looking up sub_XXX names even when the function has been renamed.

* add ability to lookup functions by previous names after a renaming.

---------

Co-authored-by: Yan Shoshitaishvili <zardus@emotionlabs.io>
2024-10-24 14:38:46 -07:00
Kevin Phoenix
fa56ba3668
Use ruff TID252 to prevent reletive imports from parents (#4916) 2024-10-01 09:06:33 -07:00
Kevin Phoenix
a3297681f2
Apply B lints (#4795) 2024-08-29 18:59:52 -07:00
Kevin Phoenix
feda6f6909
Apply ruff SIM lints (#4793)
* Apply SIM lints

* Fix some failing tests

* Fix more bugs
2024-08-29 16:56:53 -07:00
Kevin Phoenix
ee464d0338
Adopt from __future__ import annotations (#4790) 2024-08-28 18:31:43 -07:00
Audrey Dutcher
bf197cb0dc
SimType & friends: Fully typecheck, fix observed bugs (#4610)
* SimType & friends: Fully typecheck, fix observed bugs

* fix small bugs

* lint

* adjust the semantics of SimType.size - it can return None now

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* whack

* whack

* whack

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2024-07-23 17:21:42 -07:00
Yan Shoshitaishvili
6222a6cd44
Support inlining of callees during decompilation (#4595)
* rename functions_callable to functions_reachable

rename functions_callable to functions_reachable

* fix operator for Constant.__sub__

* print hex address of Function

* support multiple blocks with the same address in StackCanarySimplifier. This happens when doing inlined decompilation

* support specifying initial register values in the StackPointerTracker for inlining functions onto stacks of other functions

* add a StackPointerTracker method to retrieve all offsets of a register

* move stack pointer analysis later, in preparation of pre-inlining refactor

* split decompilation process in preparation for inlining logic

* inlined decompilation!

* testcase for inlined decompiler

* support spilled (e.g., callee-saved) register simplification in the inlined callees

* fix variable reference issue due to duplicated blocks (triggered via inlining)

* Fix more type annotations in clinic.py.

Co-authored-by: Fish <fishw@asu.edu>
2024-05-24 15:31:33 -07:00
Matt Borgerson
56fba94d1d FunctionManager: Support querying for functions by disambiguated names 2024-01-08 20:24:29 -07:00
Fish
b1886a8e27
Make CC and DEFAULT_CC platform-aware. (#4181)
* Make CC and DEFAULT_CC platform-aware. Also enhance the input variable
discovery.

* Lint code.

* compatibility fixes

* SimProcedure.project can be None.

* Add a CC for CGC. Other fixes.

* Be more conservative when analyzing call sites.
2023-09-20 19:51:52 -07:00
Matt Borgerson
17bad29fa6 tests: Structure test files into directories
* Initial pass, loosely following angr package layout
* Many updates to use the 'common' module for binaries repo
* Some unused imports and log handlers are cleaned up
2023-09-08 16:05:33 -07:00
Matt Borgerson
883f08fcd8 tests: Fixup shebangs, main functions, and mark tests executable 2023-09-07 18:46:00 -07:00
zwimer
346b2d883d black 2023-01-12 16:43:51 -07:00
Zachary Wimer
74e8f34ceb
prefer builtin constructors (#3675) 2022-12-20 16:02:02 -07:00
mborgerson
cfafb919fe
tests: Add missing __init__.py files for test discovery (#3498)
* tests: Add missing __init__.py files

* Environment::merge: Add back other environment type check

* TestEnvironment: Fix merge() rval unpacking

* TestLiveDefinitons: Fix merge() rval unpacking

* LiveDefinitions::get_sp: Don't filter out 0 values
2022-08-29 23:10:42 -07:00
simplevuln
3bbe1bb56d
Fix the infinite recursion bug in functions_called (#2377)
* Fix functions_called

Infinite recursion bug in functions_called

* Add test for functions_called

Check cyclic dependencies of functions_called

* `Function.functions_called` split tests

  * make the two cases explicitely separated

Signed-off-by: Pamplemousse <xav.maso@gmail.com>

Co-authored-by: Pamplemousse <xav.maso@gmail.com>
2020-11-07 16:31:23 -07:00
Pamplemousse
8811adb6c7
Function: Add feature to get dependencies (#2318)
Dependencies as in "the list of other functions it -transitively-
calls".

Signed-off-by: Pamplemousse <xav.maso@gmail.com>
2020-09-09 02:05:38 -07:00