AE Python APIs - SVF-tools/Software-Security-Analysis GitHub Wiki

Essential API Documentation for Labs and Assignments (Python Version)

Lab-Exercise-3

Lab-Exercise-3 still uses the dense AbstractState value object directly — loadValue / storeValue are local convenience wrappers around store / load. In Assignment-3 the same operations route through AbstractInterpretation (see below).

API Introduction
getNodeID(variable: str) -> int Retrieves the node ID of the specified variable (helper defined in the lab's AEMgr).
IntervalValue(lower: int, upper: int) Creates an interval value.
AbstractValue.getInterval() -> IntervalValue Retrieves the interval value of the abstract value.
AbstractValue.join_with(value: AbstractValue) Merges the current value with another value.
getMemObjAddress(variable: str) -> AddressValue Retrieves the memory object address of the specified variable (helper).
AddressValue(getMemObjAddress(variable: str)) Creates an address value initialized to the memory object address of the specified variable.
AbstractState.widening(other: AbstractState) -> AbstractState Returns a new AbstractState that is the widening of self with other.
AbstractState.narrowing(other: AbstractState) -> AbstractState Returns a new AbstractState that is the narrowing of self with other.
AbstractState.joinWith(other: AbstractState) Joins (in place) the current state with another state.
AbstractValue.meet_with(value: AbstractValue) Performs an intersection operation between the current value and another value.
getGepObjAddress(variable: str, offset: int) -> AddressValue Retrieves the GEP (GetElementPtr) object address of the specified variable with the given offset (helper).
AbstractState.store(addr: int, val: AbstractValue) Store an AbstractValue at virtual address addr. (Lab-Exercise-3's AEState.storeValue(varId, val) is a thin wrapper around this.)
AbstractState.load(addr: int) -> AbstractValue Load the AbstractValue at virtual address addr. (Lab-Exercise-3's AEState.loadValue(varId) is a thin wrapper.)
AbstractState.printAbstractState() Prints the abstract state for debugging purposes.

Assignment-3

Note on naming: In Assignment-3's Python skeleton, AbstractExecution keeps a reference to an AbstractInterpretation instance under the field name svf_state_mgr. The dense GEP / load / store helpers that used to live on AEState are now methods on pysvf.AbstractInterpretation. The per-ICFGNode value object is still a pysvf.AbstractState; you get one with getAbsStateFromTrace(node).

API Introduction
SVFUtil.isa(stmt.getICFGNode()) / stmt.getICFGNode().isCall() Check if the statement's containing ICFG node is a call.
stmt.asGepStmt() Downcast SVFStmt to GepStmt (returns None if not a GepStmt).
AbstractExecution.getAbsStateFromTrace(node: ICFGNode) -> AbstractState Retrieves the abstract state of the given ICFG node from the trace.
GepStmt.getLHSVarID() -> int Retrieves the left-hand side variable ID of the GepStmt.
GepStmt.getRHSVarID() -> int Retrieves the right-hand side variable ID of the GepStmt.
as[var_id].getAddrs() -> AddressValue Retrieves the addresses stored at var_id in the abstract state.
as.getIDFromAddr(addr: int) -> int Retrieves the internal object ID from a virtual address.
svfir.getBaseObject(id: int).getByteSizeOfObj() -> int Retrieves the byte size of the base object.
pysvf.Options.max_field_limit() -> int Retrieves the value of the max-field-limit option (Options.WidenDelay is C++-only — Python skeleton hard-codes the widening delay).
AbstractExecution.handleICFGNode(node: ICFGNode) Handles a singleton WTO node (Weak Topological Order).
AbstractExecution.handleICFGCycle(cycle: ICFGCycleWTO) Handles WTO cycles (a set of ICFGNodes).
cycle.head.getICFGNode() Get the cycle head ICFGNode.
AbstractExecution.mergeStatesFromPredecessors(node: ICFGNode) -> AbstractState Merges states from predecessor ICFG nodes.
CopyStmt.getLHSVarID() -> int / .getRHSVarID() -> int LHS / RHS variable IDs of a copy statement.
BinaryOPStmt.getOpVarId(index: int) -> int Retrieves the operand variable ID of the binary operation statement.
BinaryOPStmt.getResId() -> int Retrieves the result variable ID of the binary operation statement.
BinaryOPStmt.getOpcode() -> int Retrieves the opcode of the binary operation statement (compare with constants from pysvf.enums.OpCode).
CallPE.getResId() -> int Retrieves the formal-parameter variable ID for a phi-like call parameter statement.
CallPE.getOpVarNum() -> int Retrieves the number of actual-parameter operands in a phi-like CallPE.
CallPE.getOpVarId(index: int) -> int Retrieves the actual-parameter variable ID at index.
CallPE.getOpCallICFGNode(index: int) -> CallICFGNode Retrieves the call site corresponding to the actual-parameter operand at index.
self.svf_state_mgr.loadValue(pointer: ValVar, node: ICFGNode) -> AbstractValue Loads the abstract value pointed to by pointer at node. Replaces the old AEState.loadValue(varId).
self.svf_state_mgr.storeValue(pointer: ValVar, val: AbstractValue, node: ICFGNode) Stores val through pointer at node. Replaces the old AEState.storeValue(varId, val).
LoadStmt.getRHSVarID() -> int / .getLHSVarID() -> int LHS / RHS variable IDs of a load statement.
IntervalValue.getIntNumeral() -> int Returns the integer representation of the interval value.
self.svf_state_mgr.getGepByteOffset(gep: GepStmt) -> IntervalValue Retrieves the byte offset of a GEP statement. Replaces AEState.getByteOffset(gep).
self.svf_state_mgr.getGepElementIndex(gep: GepStmt) -> IntervalValue Retrieves the element index of a GEP statement. Replaces AEState.getElementIndex(gep).
self.svf_state_mgr.getGepObjAddrs(pointer: ValVar, offset: IntervalValue) -> AddressValue Retrieves the addresses of GEP objects. Replaces AEState.getGepObjAddrs(varID, offset).
AbstractExecutionHelper.reportBufOverflow(node: ICFGNode, msg: str) Reports a buffer overflow for a given ICFG node (Assignment-3 helper).
AbstractExecutionHelper.updateGepObjOffsetFromBase(abstractState: AbstractState, gepAddrs: AddressValue, objAddrs: AddressValue, offset: IntervalValue) Updates the GEP object offset from the base.
AbstractExecution.getAccessOffset(objId: int, gep: GepStmt) -> IntervalValue Returns the accessing offset of an object at a GepStmt.
AbstractExecution.updateStateOnExtCall(extCallNode: CallICFGNode) Handles external calls, checking for buffer overflows, and updates abstract states using memcpy-like APIs via AbstractExecutionHelper.handleMemcpy.
AbstractExecutionHelper.handleMemcpy(abstractState: AbstractState, dst: SVFVar, src: SVFVar, len: IntervalValue, start_idx: int) Simulates a memcpy operation in abstractState: copies len bytes from the source variable src to the destination variable dst, starting at offset start_idx. The function automatically determines the element size (for arrays or pointers) and performs element-wise copying, updating the abstract state accordingly. Only objects present in the abstract state are copied.
AbstractExecutionHelper.getStrlen(abstractState: AbstractState, strValue: SVFVar) -> IntervalValue Returns the length of a null-terminated string starting at strValue in abstractState.
AbstractExecutionHelper.addToGepObjOffsetFromBase(obj: GepObjVar, offset: IntervalValue) Adds an offset to the GEP object offset from the base object.
AbstractExecutionHelper.hasGepObjOffsetFromBase(obj: GepObjVar) -> bool Checks if there is a GEP object offset from the base object.
AbstractExecutionHelper.getGepObjOffsetFromBase(obj: GepObjVar) -> IntervalValue Retrieves the GEP object offset from the base object.
AbstractState.printAbstractState() Prints the abstract state.
AbstractState.clone() -> AbstractState Returns an independent copy. Use this before mutating a state kept in self.post_abs_trace.

self.post_abs_trace is an alias of self.svf_state_mgr, not a plain Python dictionary. Indexing it returns a reference to a C++ AbstractState; save previous loop states with .clone() before calling code that mutates the trace.

CallPE.getResId / getOpVarId / getOpCallICFGNode

CallPE is phi-like in current pysvf: the result is the formal parameter, and each operand is one actual parameter from a specific call site.

def updateStateOnCall(self, call: pysvf.CallPE):
    abstract_state = self.post_abs_trace[call.getICFGNode()]
    formal = call.getResId()
    result = AbstractValue()
    for i in range(call.getOpVarNum()):
        call_site = call.getOpCallICFGNode(i)
        if call_site in self.post_abs_trace:
            actual = call.getOpVarId(i)
            result.join_with(self.post_abs_trace[call_site][actual])
    abstract_state[formal] = result

AbstractExecutionHelper.handleMemcpy(abstractState: AbstractState, dst: SVFVar, src: SVFVar, len: IntervalValue, start_idx: int)

  • Simulates a memcpy operation in abstractState: copies len bytes from the source variable src to the destination variable dst, starting at offset start_idx. The function automatically determines the element size (for arrays or pointers) and performs element-wise copying, updating the abstract state accordingly. Only objects present in the abstract state are copied.

    For example

    # abstract_state is an AbstractState
    # dst is a pysvf.SVFVar, whose type can be Array or Pointer.
    # src is a pysvf.SVFVar, whose type can be Array or Pointer.
    # len is an IntervalValue; we copy the lower bound bytes
    # start_idx is the starting position
    # e.g. in source code,  char dst[10] = {'a','a','a','a','a','a','a','a','a','a'};
    #                       char src[5] = {'1', '2', '3', '4', '\0'};
    # we call handleMemcpy(abstract_state, dst, src, IntervalValue(5, 5), 2);
    # AbstractState should be updated as `dst = {'a', 'a', '1', '2', '3', '4','\0', 'a','a','a'}`
    # in which dst[2] = '1', dst[3] = '2', dst[4] = '3', dst[5] = '4', dst[6] = '\0', and no change occurs in other indices.
    
    self.helper.handleMemcpy(abstract_state, dst, src, length, start_idx)