binaryninja-api icon indicating copy to clipboard operation
binaryninja-api copied to clipboard

Function workflow activity that requests LLIL excessively causes the workflow machine to stall

Open WeiN76LQh opened this issue 3 months ago • 1 comments

Version and Platform (required):

  • Binary Ninja Version: 5.3.8652-dev Ultimate (f6637a1a)
  • Edition: Ultimate
  • OS: macOS
  • OS Version: 15.6
  • CPU Architecture: M1

Bug Description: A function workflow activity can cause the workflow machine to stall/freeze. In that state it can't progress or be paused. The following is a single file native plugin that reproduces the issue.

#include "binaryninjaapi.h"
#include <lowlevelilinstruction.h>

using namespace BinaryNinja;

static void Action(Ref<AnalysisContext> ctx)
{
    const auto func = ctx->GetFunction();
    const auto bv = func->GetView();

    const auto funcAddr = func->GetStart();

    const auto llil = ctx->GetLowLevelILFunction();
    if (!llil)
        return;

    const auto addressSize = bv->GetAddressSize();
    const auto linkRegister = func->GetArchitecture()->GetLinkRegister();

    bool updated = false;
    for (const auto& block : llil->GetBasicBlocks()) {
        for (size_t i = block->GetStart(), end = block->GetEnd(); i < end; ++i) {
            const auto insn = llil->GetInstruction(i);
            if (insn.operation != LLIL_CALL && insn.operation != LLIL_TAILCALL)
                continue;

            const auto callExpr = insn.GetDestExpr();
            const auto targetAddr = callExpr.GetValue().value;

            const auto targetFunc = bv->GetAnalysisFunction(func->GetPlatform(), targetAddr);
            if (!targetFunc)
                continue;

            const auto targetFuncLLIL = targetFunc->GetLowLevelIL();
        }
    }
}

extern "C" {

BN_DECLARE_CORE_ABI_VERSION

static constexpr auto FunctionWorkflowInfo = R"#({
    "title": "Issue 7692",
    "description": "",
    "targetType" : "function"
})#";

BINARYNINJAPLUGIN bool CorePluginInit()
{
    const auto functionWorkflow = Workflow::Instance("core.function.metaAnalysis")->Clone("core.function.issue");
    const auto config = R"#({"name":"core.function.issue.crash","title":"Causes a crash","description":"","role":"action","eligibility":{"auto": {},"predicates": [{"type": "viewType", "value": ["DSCView","Mach-O"], "operator": "in"}]}})#";
    const auto activity = new Activity(config, &Action);
    functionWorkflow->RegisterActivity(activity);
    functionWorkflow->Insert("core.function.generateMediumLevelIL", "core.function.issue.crash");
    Workflow::RegisterWorkflow(functionWorkflow, FunctionWorkflowInfo);
    return true;
}
}

Steps To Reproduce: Please provide all steps required to reproduce the behavior:

  1. Compile the native plugin code above and install it.
  2. Right-click open with options a copy of the DYLD Shared Cache (might be fine to try against other binaries) and make sure to select the workflow (core.function.issue) added by the plugin.
  3. Observe the workflow machine stalling pretty much immediately.

WeiN76LQh avatar Nov 25 '25 04:11 WeiN76LQh

Honestly this might not really be a bug and more of just using things wrong. I guess requesting lots of LLIL while LLIL is being generated will lead to potential lock ups due to recursion-ish related stuff. I'm trying to minimally reproduce another issue where it seems requesting LLIL during a workflow is caused function update counts to reach the maximum and analysis to fail.

WeiN76LQh avatar Nov 25 '25 04:11 WeiN76LQh