Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions Delegate/SearchMatchDelegate.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System;
using System.Runtime.ExceptionServices;

namespace BinaryNinja
{
/// <summary>
/// Receives a match in an in-memory search buffer.
/// </summary>
/// <param name="offset">Byte offset of the match in the buffer.</param>
/// <param name="length">Length of the match in bytes.</param>
/// <returns>True to continue searching, or false to cancel.</returns>
public delegate bool SearchMatchDelegate(ulong offset, ulong length);

internal sealed class SearchMatchContext
{
private readonly SearchMatchDelegate callback;
private ExceptionDispatchInfo? exception;

internal SearchMatchContext(SearchMatchDelegate callback)
{
this.callback = callback;
}

internal bool Invoke(IntPtr context, ulong offset, ulong length)
{
if (null != this.exception)
{
return false;
}

try
{
return this.callback(offset, length);
}
catch (Exception caught)
{
this.exception = ExceptionDispatchInfo.Capture(caught);
return false;
}
}

internal void ThrowIfFailed()
{
if (null != this.exception)
{
this.exception.Throw();
}
}
}
}
48 changes: 46 additions & 2 deletions Misc/CoreUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1178,6 +1178,52 @@ public static bool VersionLessThan(VersionInfo smaller , VersionInfo larger)
}
}

/// <summary>
/// Searches an in-memory buffer using the core's advanced search query format.
/// </summary>
/// <param name="query">JSON search query accepted by the advanced binary search engine.</param>
/// <param name="buffer">Bytes to search.</param>
/// <param name="match">Callback receiving each match offset and length.</param>
/// <returns>True when the search completed, or false when the callback cancelled it.</returns>
public static unsafe bool PerformSearch(
string query,
byte[] buffer,
SearchMatchDelegate match)
{
if (null == query)
{
throw new ArgumentNullException(nameof(query));
}

if (null == buffer)
{
throw new ArgumentNullException(nameof(buffer));
}

if (null == match)
{
throw new ArgumentNullException(nameof(match));
}

SearchMatchContext callbackContext = new SearchMatchContext(match);
NativeDelegates.BNProgressFunction nativeCallback = callbackContext.Invoke;
bool result;

fixed (byte* bufferPointer = buffer)
{
result = NativeMethods.BNPerformSearch(
query,
(IntPtr)bufferPointer,
(ulong)buffer.Length,
Marshal.GetFunctionPointerForDelegate<NativeDelegates.BNProgressFunction>(nativeCallback),
IntPtr.Zero);
}

GC.KeepAlive(nativeCallback);
callbackContext.ThrowIfFailed();
return result;
}

/// <summary>
/// Executes a worker process with the given arguments, input data, and captures stdout/stderr.
/// </summary>
Expand Down Expand Up @@ -1403,8 +1449,6 @@ public static unsafe string[] ParseTypeParserOptionsText(string optionsText)
// TODO: BNPerformCustomRequest / BNPerformDownloadRequest — on DownloadInstance,
// requires callback context parameters for progress/completion notifications.

// TODO: BNPerformSearch — on BinaryView, requires callback context for search results.

// TODO: BNTypeArchiveMergeSnapshots / BNTypeArchiveNewSnapshotTransaction —
// callback-based transaction functions requiring managed delegate infrastructure.

Expand Down
Loading