Intermittent crash during auto-analysis after loading an image using the DSC plugin
Version and Platform (required):
- Binary Ninja Version: 4.3.7094-dev (0f9d9b3f)
- OS: macOS
- OS Version: 15.2
- CPU Architecture: M1
Bug Description: A NULL pointer dereference (it would seem) is occurring during auto-analysis that is triggered when loading an image in the DSC. It doesn't seem to matter to much which image.
Steps To Reproduce:
- Load a copy of the DYLD Shared Cache in Binary Ninja.
- Wait for
libsystem_c.dylibto finish loading and for auto-analysis to complete. - Load the
Foundationimage.
I can only reproduce it when I have my plugin running which has some function workflow activities. It seems to happen 100% of the time when I follow the steps above. I'll see if I can figure out what function workflow work is being done that causes the crash if needs be.
Screenshots/Video Recording: The following backtrace is where the crash occurs. This is on a function workflow advanced analysis thread.
___lldb_unnamed_symbol16373 (@___lldb_unnamed_symbol16373:418)
___lldb_unnamed_symbol5841 (@___lldb_unnamed_symbol5841:19)
___lldb_unnamed_symbol15247 (@___lldb_unnamed_symbol15247:158)
___lldb_unnamed_symbol16152 (@___lldb_unnamed_symbol16152:15)
___lldb_unnamed_symbol6689 (@___lldb_unnamed_symbol6689:20)
___lldb_unnamed_symbol29583 (@___lldb_unnamed_symbol29583:706)
___lldb_unnamed_symbol29611 (@___lldb_unnamed_symbol29611:101)
___lldb_unnamed_symbol29600 (@___lldb_unnamed_symbol29600:10)
___lldb_unnamed_symbol29856 (@___lldb_unnamed_symbol29856:18)
___lldb_unnamed_symbol27078 (@___lldb_unnamed_symbol27078:18)
___lldb_unnamed_symbol29255 (@___lldb_unnamed_symbol29255:850)
___lldb_unnamed_symbol29250 (@___lldb_unnamed_symbol29250:6)
_pthread_start (@_pthread_start:37)
Additional Information: Starting happening on more recent dev versions - probably at least 4.3.7060, but couldn't be 100% sure. It may actually be do with some changes I made to my own plugin rather than a Binary Ninja version.
Are you able to share the plugin with us? There are a lot of sharp edges that can be going on with your activity that could cause this so it would help greatly.
I can't unfortunately but I am slowly trying to triage the issue
The following is a single file native plugin that triggers the issue:
#include "binaryninjaapi.h"
#include <mediumlevelilinstruction.h>
using namespace BinaryNinja;
static void Action(Ref<AnalysisContext> ctx)
{
const auto func = ctx->GetFunction();
const auto bv = func->GetView();
const auto mlil = ctx->GetMediumLevelILFunction();
if (!mlil)
return;
const auto ssa = mlil->GetSSAForm();
if (!ssa)
return;
for (const auto& block : ssa->GetBasicBlocks()) {
for (size_t i = block->GetStart(), end = block->GetEnd(); i < end; ++i) {
const auto insn = ssa->GetInstruction(i);
if (insn.operation != MLIL_CALL_SSA)
continue;
const auto callExpr = insn.GetDestExpr();
const auto targetAddr = callExpr.GetValue().value;
const auto params = insn.GetParameterExprs();
for (const auto& param : params) {
const auto paramValue = param.GetValue();
if (paramValue.state != StackFrameOffset)
continue;
const auto stackOffset = paramValue.value;
func->CreateAutoStackVariable(stackOffset, Type::IntegerType(8, true), fmt::format("foo_{:x}", stackOffset));
}
}
}
}
extern "C" {
BN_DECLARE_CORE_ABI_VERSION
static constexpr auto FunctionWorkflowInfo = R"#({
"title": "Issue 6518",
"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->InsertAfter("core.function.generateMediumLevelIL", "core.function.issue.crash");
Workflow::RegisterWorkflow(functionWorkflow, FunctionWorkflowInfo);
return true;
}
}
Install this plugin and then open a copy of the DSC and make sure to change the function workflow to this one (core.function.issue.crash). I find this will crash immediately during initial load of libsystem_c.dylib.
Seems there's an issue with creating auto stack variables. In my own plugin I don't spam them this hard, this is just to reproduce the issue and it does it much quicker this way.
Are there any plans to look at fixing this or potential work arounds? I tested on 5.3.8652-dev Ultimate (f6637a1a) and its still an instant crash. It means that function workflow activities that are used for identifying and creating stack variables are likely to cause a crash when enabled for larger binary views like for the DYLD Shared Cache. I'm not sure of another good way of going about this. My understanding is that this is one of the intended use cases of function workflows but I can't really use it in that way because of the chances of crashing.
Sorry, missed the full example plugin, trying to reproduce it now.
This currently crashes almost immediately within HighLevelILTranslator::MapExprWithType due to a null dereference introduced in 5.2.8458 (https://github.com/Vector35/binaryninja/commit/9ff892c91ca0490e84f7ba0297e16b88bc4600aa).