mirror of
https://github.com/angr/angr
synced 2026-08-17 12:23:11 -04:00
65 lines
2.2 KiB
Python
65 lines
2.2 KiB
Python
#!/usr/bin/env python3
|
|
# pylint: disable=missing-class-docstring
|
|
"""Regression test: parse_from_cmsg assigned the protobuf RepeatedScalarContainer
|
|
directly to Function.previous_names instead of converting it to a plain list.
|
|
This breaks pickling of Function objects.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pickle
|
|
import tempfile
|
|
import unittest
|
|
|
|
import angr
|
|
from angr.codenode import BlockNode
|
|
from angr.knowledge_plugins.functions.function import Function
|
|
|
|
|
|
class TestFunctionParserPreviousNames(unittest.TestCase):
|
|
def test_parsed_previous_names_is_plain_list_and_picklable(self):
|
|
blob = bytes.fromhex("c3") # ret
|
|
addr = 0x400000
|
|
|
|
with tempfile.NamedTemporaryFile(suffix=".bin", delete=False) as f:
|
|
f.write(blob)
|
|
blob_path = f.name
|
|
|
|
proj = angr.Project(
|
|
blob_path,
|
|
main_opts={
|
|
"backend": "blob",
|
|
"base_addr": addr,
|
|
"arch": "AMD64",
|
|
"entry_point": addr,
|
|
},
|
|
auto_load_libs=False,
|
|
)
|
|
|
|
fm = proj.kb.functions
|
|
func = fm.function(addr=addr, create=True)
|
|
assert func is not None
|
|
func._register_node(True, BlockNode(addr, 1, bytestr=blob))
|
|
func.name = "original_name"
|
|
func.name = "renamed" # records "original_name" in previous_names
|
|
self.assertIn("original_name", func.previous_names)
|
|
expected = list(func.previous_names)
|
|
|
|
cmsg = func.serialize_to_cmessage()
|
|
loaded = Function.parse_from_cmessage(cmsg, function_manager=fm, project=proj)
|
|
|
|
# previous_names must be a plain list, not a live protobuf container
|
|
self.assertIs(type(loaded.previous_names), list)
|
|
self.assertEqual(loaded.previous_names, expected)
|
|
|
|
# mutating the parsed function must not alias back into the cmsg
|
|
loaded.previous_names.append("another_name")
|
|
self.assertEqual(list(cmsg.previous_names), expected)
|
|
|
|
# the parsed function must round-trip through pickle
|
|
unpickled = pickle.loads(pickle.dumps(loaded))
|
|
self.assertEqual(unpickled.previous_names, [*expected, "another_name"])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|