diff --git a/pybind/AE.cpp b/pybind/AE.cpp index 71b0f1c..abe174f 100644 --- a/pybind/AE.cpp +++ b/pybind/AE.cpp @@ -750,6 +750,10 @@ void bind_abstract_state(py::module& m) { .def("__getitem__", [](AbstractStateManager& self, const ICFGNode* node) -> AbstractState& { return self[node]; }, py::arg("node"), py::return_value_policy::reference) + .def("__setitem__", [](AbstractStateManager& self, const ICFGNode* node, const AbstractState& state) { + self.updateAbstractState(node, state); + }, py::arg("node"), py::arg("state")) + .def("__contains__", &AbstractStateManager::hasAbstractState, py::arg("node")) // Def/Use site queries .def("getUseSitesOfObjVar", &AbstractStateManager::getUseSitesOfObjVar, diff --git a/pysvf/pysvf.pyi b/pysvf/pysvf.pyi index bd0191a..22ad98c 100644 --- a/pysvf/pysvf.pyi +++ b/pysvf/pysvf.pyi @@ -531,6 +531,9 @@ class GepStmt(AssignStmt): def getSrcPointeeType(self) -> "SVFType": ... """Get the source pointee type""" + def getStructFieldOffset(self, idx_var: "ValVar", struct_type: "SVFStructType") -> int: ... + """Compute the byte offset for a struct field index""" + class MultiOpndStmt(SVFStmt): def getOpVar(self, ID: int) -> "SVFVar": ... """Get the operand variable""" @@ -1964,16 +1967,10 @@ class AbstractState: def bottom(self) -> None: ... def getIDFromAddr(self, addr: int) -> int: ... def top(self) -> None: ... - def getElementIndex(self, gep: 'GepStmt') -> IntervalValue: ... - def getByteOffset(self, gep: 'GepStmt') -> IntervalValue: ... - def getPointeeElement(self, var_id: int) -> SVFType: ... def isVirtualMemAddress(self, val: int) -> bool: ... def getVirtualMemAddress(self, idx: int) -> int: ... def isCmpBranchFeasible(self, cmp: 'CmpStmt', succ: int, abstract_state: AbstractState) -> bool: ... def isSwitchBranchFeasible(self, switch_var: SVFVar, succ: int, abstract_state: AbstractState) -> bool: ... - def storeValue(self, varId: int, val: AbstractValue) -> None: ... - def loadValue(self, varId: int) -> AbstractValue: ... - def getAllocaInstByteSize(self, addr: AddrStmt) -> int: ... def inVarToValTable(self, var_id: int) -> bool: ... def inVarToAddrsTable(self, var_id: int) -> bool: ... def inAddrToAddrsTable(self, id: int) -> bool: ... @@ -1986,7 +1983,6 @@ class AbstractState: """Check if an address is freed memory""" def hash(self) -> int: ... """Get the hash of this abstract state""" - def getGepObjAddrs(self, var_id: int, offset: IntervalValue) -> AddressValue: ... def clear(self) -> None: ... def clone(self) -> 'AbstractState': ... @@ -2001,7 +1997,57 @@ class AbstractState: def isBlackHoleObjAddr(self, addr: int) -> bool: ... -class PointsTo(Set[int]): +class AbstractStateManager: + """Manages abstract states across ICFG nodes and provides the + sparsity-aware GEP / load / store / size helpers that used to live on + AbstractState (moved upstream by the Semi-Sparse refactor).""" + + def __init__(self, svfir: 'SVFIR', pta: 'AndersenWaveDiff') -> None: ... + + def getAbstractValue(self, var: 'SVFVar', node: 'ICFGNode') -> AbstractValue: ... + def hasAbstractValue(self, var: 'SVFVar', node: 'ICFGNode') -> bool: ... + def updateAbstractValue(self, var: 'SVFVar', val: AbstractValue, node: 'ICFGNode') -> None: ... + + def getAbstractState(self, node: 'ICFGNode') -> AbstractState: ... + def hasAbstractState(self, node: 'ICFGNode') -> bool: ... + def updateAbstractState(self, node: 'ICFGNode', state: AbstractState) -> None: ... + + def getGepElementIndex(self, gep: 'GepStmt') -> IntervalValue: ... + def getGepByteOffset(self, gep: 'GepStmt') -> IntervalValue: ... + def getGepObjAddrs(self, pointer: 'ValVar', offset: IntervalValue) -> AddressValue: ... + + def loadValue(self, pointer: 'ValVar', node: 'ICFGNode') -> AbstractValue: ... + def storeValue(self, pointer: 'ValVar', val: AbstractValue, node: 'ICFGNode') -> None: ... + + def getPointeeElement(self, var: 'ObjVar', node: 'ICFGNode') -> 'SVFType': ... + def getAllocaInstByteSize(self, addr: 'AddrStmt') -> int: ... + + def getTrace(self) -> dict: ... + def __getitem__(self, node: 'ICFGNode') -> AbstractState: ... + def __setitem__(self, node: 'ICFGNode', state: AbstractState) -> None: ... + def __contains__(self, node: 'ICFGNode') -> bool: ... + + def getUseSitesOfObjVar(self, obj: 'ObjVar', node: 'ICFGNode') -> set: ... + def getUseSitesOfValVar(self, var: 'ValVar') -> set: ... + def getDefSiteOfValVar(self, var: 'ValVar') -> 'ICFGNode': ... + def getDefSiteOfObjVar(self, obj: 'ObjVar', node: 'ICFGNode') -> 'ICFGNode': ... + + +class AbstractInterpretation: + """Minimal binding -- exposes getStateMgr() so Python can grab the + AbstractStateManager from a running analysis.""" + + def getStateMgr(self) -> AbstractStateManager: ... + + +class Options: + """A small subset of SVF Options exposed for downstream Python code.""" + + @staticmethod + def max_field_limit() -> int: ... + + +class PointsTo(Set[int]): def set(self, value: int) -> None: ... diff --git a/stubtest_allowlist.txt b/stubtest_allowlist.txt index 612b767..2a2f460 100644 --- a/stubtest_allowlist.txt +++ b/stubtest_allowlist.txt @@ -1,5 +1,10 @@ pysvf.AbstractState +pysvf.AbstractStateManager +pysvf.AbstractInterpretation +pysvf.AbstractInterpretation.__init__ pysvf.AbstractValue +pysvf.Options +pysvf.Options.__init__ pysvf.ActualINSVFGNode pysvf.ActualINSVFGNode.__init__ pysvf.ActualOUTSVFGNode