Skip to main content
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

FieldDescriptionType
nameFunction namestring
addressFunction addressAddressValue
total_bytesFunction length in bytes, calculated as the sum of the sizes of all its code blocksnumber

Methods

MethodDescriptionParametersReturn Type
callsReturns a table of addresses for calls to the specified function(s)string, AddressValue, or CallsToQueryAddressValue[]
has_callReturns true if the function contains a call to the specified function(s)string, AddressValue, or CallsToQueryboolean
namedReturns true if the function name matches the provided namestringboolean
findSearches for a pattern in the function’s codePatternMatcherAddressValue
matchesReturns true if the function’s code matches the given patternPatternMatcherboolean
blocksReturns every basic block in the function as IR termsIRTerm[]
prototypeReturns the inferred prototype for the function entry when availableIRTerm
is_reachableReturns true if execution can flow from the first address to the second address(AddressValue, AddressValue)boolean
dominatesReturns true if the first address is in a block that dominates the block containing the second address(AddressValue, AddressValue)boolean
precedesReturns 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
}