The FunctionContext object provides access to information and utilities related to a specific function in the binary.
It is used in VulHunt rules to inspect function properties, search for patterns, and analyze function calls.
Fields
| Field | Description | Type |
|---|
name | Function name | string |
address | Function address | AddressValue |
total_bytes | Function length in bytes, calculated as the sum of the sizes of all its code blocks | number |
Methods
| Method | Description | Parameters | Return Type |
|---|
calls | Returns a table of addresses for calls to the specified function(s) | string, AddressValue, or CallsToQuery | AddressValue[] |
has_call | Returns true if the function contains a call to the specified function(s) | string, AddressValue, or CallsToQuery | boolean |
named | Returns true if the function name matches the provided name | string | boolean |
find | Searches for a pattern in the function’s code | PatternMatcher | AddressValue |
matches | Returns true if the function’s code matches the given pattern | PatternMatcher | boolean |
blocks | Returns every basic block in the function as IR terms | — | IRTerm[] |
prototype | Returns the inferred prototype for the function entry when available | — | IRTerm |
is_reachable | Returns true if execution can flow from the first address to the second address | (AddressValue, AddressValue) | boolean |
dominates | Returns true if the first address is in a block that dominates the block containing the second address | (AddressValue, AddressValue) | boolean |
precedes | Returns true if the first address can reach the second and the second does not dominate the first | (AddressValue, AddressValue) | boolean |
Reference
name
The name field contains the name of the function.
address
The address field contains the address of the function in the binary.
total_bytes
The total_bytes field returns the function length in bytes, calculated as the sum of the sizes of all its code blocks.
calls
The calls method returns a table of addresses where the current function calls the specified function(s). Accepts a string (function name), AddressValue (function address), or CallsToQuery for pattern matching.
Returns an empty table when the specified function is not found.
has_call
The has_call method returns true if the function contains a call to the specified function(s). Accepts a string (function name), AddressValue (function address), or CallsToQuery for pattern matching.
named
The named method returns true if the function name matches the provided name.
find
The find method searches for a pattern in the function’s code and returns the address of the match, if found.
matches
The matches method returns true if the function’s code matches the given pattern.
blocks
The blocks method returns every basic block in the function as IRTerm objects. Each item can be traversed to inspect instructions, operands, or metadata.
prototype
The prototype method returns the inferred prototype as an IRTerm for the function entry if one is available, otherwise nil.
is_reachable
The is_reachable method takes two AddressValue objects and reports whether execution can flow from the first address to the second inside the current function.
dominates
The dominates method returns true when the basic block that contains the first AddressValue dominates the block that contains the second address.
precedes
The precedes method returns true when the first address can reach the second and the second does not dominate the first, allowing you to assert ordering without full dominance math.
Example
-- Detect a missing bounds check: target_function calls memcpy
-- but the length argument may not be validated by a prior strlen call.
scopes = scope:functions{
named = "target_function",
with = function(project, context)
-- Only proceed if the function calls memcpy
if not context:has_call("memcpy") then return end
local memcpy_calls = context:calls("memcpy")
local strlen_calls = context:calls("strlen")
-- For each memcpy call site, check whether a strlen call
-- precedes it. If not, the length may be unchecked.
for _, memcpy_addr in ipairs(memcpy_calls) do
local has_prior_check = false
for _, strlen_addr in ipairs(strlen_calls) do
if context:precedes(strlen_addr, memcpy_addr) then
has_prior_check = true
break
end
end
if not has_prior_check then
-- Return a finding
return result:high{...}
end
end
-- Search for a known byte pattern in the function body
local pattern = PatternMatcher.new("55 .. 89 E5 48")
if context:matches(pattern) then
local match_addr = context:find(pattern)
end
-- Walk the basic blocks of the function
for _, block in ipairs(context:blocks()) do
-- Each block is an IRTerm that can be inspected further
end
end
}