summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Smith <glenn@vector35.com>2023-11-14 18:35:38 -0500
committerGlenn Smith <glenn@vector35.com>2023-11-14 18:35:38 -0500
commit4025361513068463390900635313910200542556 (patch)
tree2dbfc8ef20c3eae8d849a02d833917dc24b28d28
parent814d840c8d12dfcfb60a5bf172ea494825fd30c1 (diff)
Fix a number of leaks and bad uses of free in the api
See https://github.com/Vector35/binaryninja-api/issues/4751
-rw-r--r--architecture.cpp8
-rw-r--r--binaryninjaapi.h4
-rw-r--r--binaryninjacore.h5
-rw-r--r--binaryview.cpp16
-rw-r--r--datarenderer.cpp7
-rw-r--r--debuginfo.cpp22
-rw-r--r--flowgraphnode.cpp8
-rw-r--r--function.cpp27
-rw-r--r--interaction.cpp6
-rw-r--r--metadata.cpp1
-rw-r--r--python/datarender.py24
-rw-r--r--relocationhandler.cpp1
-rw-r--r--type.cpp1
13 files changed, 105 insertions, 25 deletions
diff --git a/architecture.cpp b/architecture.cpp
index 0e09230a..a1f6292e 100644
--- a/architecture.cpp
+++ b/architecture.cpp
@@ -2429,7 +2429,13 @@ vector<DisassemblyTextLine> DisassemblyTextRenderer::PostProcessInstructionTextL
size_t count = 0;
result = BNPostProcessDisassemblyTextRendererLines(
m_object, addr, len, inLines, lines.size(), &count, indentSpaces.c_str());
- BNFreeDisassemblyTextLines(inLines, lines.size());
+
+ for (size_t i = 0; i < lines.size(); i++)
+ {
+ InstructionTextToken::FreeInstructionTextTokenList(inLines[i].tokens, inLines[i].count);
+ Tag::FreeTagList(inLines[i].tags, inLines[i].tagCount);
+ }
+ delete[] inLines;
vector<DisassemblyTextLine> outLines;
for (size_t i = 0; i < count; i++)
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index 32db3582..0052e3ed 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -3625,6 +3625,7 @@ namespace BinaryNinja {
static BNTag** CreateTagList(const std::vector<Ref<Tag>>& tags, size_t* count);
static std::vector<Ref<Tag>> ConvertTagList(BNTag** tags, size_t count);
+ static void FreeTagList(BNTag** tags, size_t count);
static std::vector<Ref<Tag>> ConvertAndFreeTagList(BNTag** tags, size_t count);
};
@@ -3655,6 +3656,7 @@ namespace BinaryNinja {
static BNTagReference* CreateTagReferenceList(const std::vector<TagReference>& tags, size_t* count);
static std::vector<TagReference> ConvertTagReferenceList(BNTagReference* tags, size_t count);
+ static void FreeTagReferenceList(BNTagReference* tags, size_t count);
static std::vector<TagReference> ConvertAndFreeTagReferenceList(BNTagReference* tags, size_t count);
};
@@ -9470,6 +9472,7 @@ namespace BinaryNinja {
static PossibleValueSet FromAPIObject(BNPossibleValueSet& value);
BNPossibleValueSet ToAPIObject();
+ static void FreeAPIObject(BNPossibleValueSet* value);
};
class FlowGraph;
@@ -15255,6 +15258,7 @@ namespace BinaryNinja {
BNType* type, const BNInstructionTextToken* prefix, size_t prefixCount, size_t width, size_t* count,
BNTypeContext* typeCxt, size_t ctxCount);
static void FreeCallback(void* ctxt);
+ static void FreeLinesCallback(void* ctxt, BNDisassemblyTextLine* lines, size_t count);
public:
DataRenderer();
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 57ee5eb6..06ec52cb 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -37,14 +37,14 @@
// Current ABI version for linking to the core. This is incremented any time
// there are changes to the API that affect linking, including new functions,
// new types, or modifications to existing functions or types.
-#define BN_CURRENT_CORE_ABI_VERSION 41
+#define BN_CURRENT_CORE_ABI_VERSION 42
// Minimum ABI version that is supported for loading of plugins. Plugins that
// are linked to an ABI version less than this will not be able to load and
// will require rebuilding. The minimum version is increased when there are
// incompatible changes that break binary compatibility, such as changes to
// existing types or functions.
-#define BN_MINIMUM_CORE_ABI_VERSION 41
+#define BN_MINIMUM_CORE_ABI_VERSION 42
#ifdef __GNUC__
#ifdef BINARYNINJACORE_LIBRARY
@@ -2791,6 +2791,7 @@ extern "C"
BNDisassemblyTextLine* (*getLinesForData)(void* ctxt, BNBinaryView* view, uint64_t addr, BNType* type,
const BNInstructionTextToken* prefix, size_t prefixCount, size_t width, size_t* count,
BNTypeContext* typeCtx, size_t ctxCount);
+ void (*freeLines)(void* ctx, BNDisassemblyTextLine* lines, size_t count);
} BNCustomDataRenderer;
typedef enum BNSegmentFlag
diff --git a/binaryview.cpp b/binaryview.cpp
index 077f2b4a..7abb01cb 100644
--- a/binaryview.cpp
+++ b/binaryview.cpp
@@ -769,6 +769,13 @@ std::vector<Ref<Tag>> Tag::ConvertTagList(BNTag** tags, size_t count)
}
+void Tag::FreeTagList(BNTag** tags, size_t count)
+{
+ delete[] tags;
+ (void)count;
+}
+
+
std::vector<Ref<Tag>> Tag::ConvertAndFreeTagList(BNTag** tags, size_t count)
{
auto result = ConvertTagList(tags, count);
@@ -859,6 +866,13 @@ std::vector<TagReference> TagReference::ConvertTagReferenceList(BNTagReference*
}
+void TagReference::FreeTagReferenceList(BNTagReference* tags, size_t count)
+{
+ delete[] tags;
+ (void)count;
+}
+
+
std::vector<TagReference> TagReference::ConvertAndFreeTagReferenceList(BNTagReference* tags, size_t count)
{
auto result = ConvertTagReferenceList(tags, count);
@@ -3621,6 +3635,7 @@ bool BinaryView::ParseTypeString(const string& source, map<QualifiedName, Ref<Ty
errors = errorStr;
BNFreeString(errorStr);
}
+ delete[] typesList.names;
if (!ok)
return false;
@@ -3675,6 +3690,7 @@ bool BinaryView::ParseTypesFromSource(const string& source, const vector<string>
errors = errorStr;
BNFreeString(errorStr);
}
+ delete[] typesList.names;
if (!ok)
return false;
diff --git a/datarenderer.cpp b/datarenderer.cpp
index 40c64d66..a2ed1dae 100644
--- a/datarenderer.cpp
+++ b/datarenderer.cpp
@@ -17,6 +17,7 @@ DataRenderer::DataRenderer()
renderer.freeObject = FreeCallback;
renderer.isValidForData = IsValidForDataCallback;
renderer.getLinesForData = GetLinesForDataCallback;
+ renderer.freeLines = FreeLinesCallback;
AddRefForRegistration();
m_object = BNCreateDataRenderer(&renderer);
}
@@ -106,6 +107,12 @@ void DataRenderer::FreeCallback(void* ctxt)
}
+void DataRenderer::FreeLinesCallback(void* ctxt, BNDisassemblyTextLine* lines, size_t count)
+{
+ delete[] lines;
+}
+
+
bool DataRenderer::IsValidForData(BinaryView* data, uint64_t addr, Type* type, vector<pair<Type*, size_t>>& context)
{
BNTypeContext* typeCtx = new BNTypeContext[context.size()];
diff --git a/debuginfo.cpp b/debuginfo.cpp
index 5fef18d2..33cf67a8 100644
--- a/debuginfo.cpp
+++ b/debuginfo.cpp
@@ -276,20 +276,20 @@ bool DebugInfo::AddType(const string& name, Ref<Type> type)
bool DebugInfo::AddFunction(const DebugFunctionInfo& function)
{
- BNDebugFunctionInfo* input = new BNDebugFunctionInfo();
+ BNDebugFunctionInfo input;
- input->shortName = function.shortName.size() ? BNAllocString(function.shortName.c_str()) : nullptr;
- input->fullName = function.fullName.size() ? BNAllocString(function.fullName.c_str()) : nullptr;
- input->rawName = function.rawName.size() ? BNAllocString(function.rawName.c_str()) : nullptr;
- input->address = function.address;
- input->type = function.type ? function.type->GetObject() : nullptr;
- input->platform = function.platform ? function.platform->GetObject() : nullptr;
+ input.shortName = function.shortName.size() ? BNAllocString(function.shortName.c_str()) : nullptr;
+ input.fullName = function.fullName.size() ? BNAllocString(function.fullName.c_str()) : nullptr;
+ input.rawName = function.rawName.size() ? BNAllocString(function.rawName.c_str()) : nullptr;
+ input.address = function.address;
+ input.type = function.type ? function.type->GetObject() : nullptr;
+ input.platform = function.platform ? function.platform->GetObject() : nullptr;
- bool result = BNAddDebugFunction(m_object, input);
+ bool result = BNAddDebugFunction(m_object, &input);
- BNFreeString(input->shortName);
- BNFreeString(input->fullName);
- BNFreeString(input->rawName);
+ BNFreeString(input.shortName);
+ BNFreeString(input.fullName);
+ BNFreeString(input.rawName);
return result;
}
diff --git a/flowgraphnode.cpp b/flowgraphnode.cpp
index 5021e842..cf25b80c 100644
--- a/flowgraphnode.cpp
+++ b/flowgraphnode.cpp
@@ -131,7 +131,13 @@ void FlowGraphNode::SetLines(const vector<DisassemblyTextLine>& lines)
}
BNSetFlowGraphNodeLines(m_object, buf, lines.size());
- BNFreeDisassemblyTextLines(buf, lines.size());
+
+ for (size_t i = 0; i < lines.size(); i++)
+ {
+ InstructionTextToken::FreeInstructionTextTokenList(buf[i].tokens, buf[i].count);
+ Tag::FreeTagList(buf[i].tags, buf[i].tagCount);
+ }
+ delete[] buf;
m_cachedLines = lines;
m_cachedLinesValid = true;
diff --git a/function.cpp b/function.cpp
index 4ef91860..b95ed211 100644
--- a/function.cpp
+++ b/function.cpp
@@ -538,6 +538,31 @@ BNPossibleValueSet PossibleValueSet::ToAPIObject()
}
+void PossibleValueSet::FreeAPIObject(BNPossibleValueSet* value)
+{
+ switch (value->state)
+ {
+ case SignedRangeValue:
+ case UnsignedRangeValue:
+ delete[] value->ranges;
+ break;
+ case LookupTableValue:
+ for (size_t i = 0; i < value->count; i ++)
+ {
+ delete[] value->table[i].fromValues;
+ }
+ delete[] value->table;
+ break;
+ case InSetOfValues:
+ case NotInSetOfValues:
+ delete[] value->valueSet;
+ break;
+ default:
+ break;
+ }
+}
+
+
DataBuffer Function::GetConstantData(BNRegisterValueType state, uint64_t value, size_t size)
{
return DataBuffer(BNGetConstantData(m_object, state, value, size));
@@ -2533,6 +2558,8 @@ void Function::SetUserVariableValue(const Variable& var, uint64_t defAddr, Possi
auto valueObj = value.ToAPIObject();
BNSetUserVariableValue(m_object, &var_data, &defSite, &valueObj);
+
+ PossibleValueSet::FreeAPIObject(&valueObj);
}
diff --git a/interaction.cpp b/interaction.cpp
index 037edca6..5b62084e 100644
--- a/interaction.cpp
+++ b/interaction.cpp
@@ -661,7 +661,10 @@ bool BinaryNinja::GetFormInput(vector<FormInputField>& fields, const string& tit
// If user cancelled, there are no results
if (!ok)
+ {
+ delete[] fieldBuf;
return false;
+ }
// Copy results to API structures
for (size_t i = 0; i < fields.size(); i++)
@@ -689,7 +692,10 @@ bool BinaryNinja::GetFormInput(vector<FormInputField>& fields, const string& tit
}
}
+ // Free core-allocated results
BNFreeFormInputResults(fieldBuf, fields.size());
+
+ delete[] fieldBuf;
return true;
}
diff --git a/metadata.cpp b/metadata.cpp
index c1ba34a3..409ea47b 100644
--- a/metadata.cpp
+++ b/metadata.cpp
@@ -55,6 +55,7 @@ Metadata::Metadata(const std::vector<Ref<Metadata>>& data)
dataList[i] = data[i]->m_object;
m_object = BNCreateMetadataArray(dataList, data.size());
+ delete[] dataList;
}
Metadata::Metadata(const std::map<std::string, Ref<Metadata>>& data)
diff --git a/python/datarender.py b/python/datarender.py
index 54c7703d..0305785f 100644
--- a/python/datarender.py
+++ b/python/datarender.py
@@ -91,6 +91,7 @@ class DataRenderer:
self._cb.freeObject = self._cb.freeObject.__class__(self._free_object)
self._cb.isValidForData = self._cb.isValidForData.__class__(self._is_valid_for_data)
self._cb.getLinesForData = self._cb.getLinesForData.__class__(self._get_lines_for_data)
+ self._cb.freeLines = self._cb.freeLines.__class__(self._free_lines)
self.handle = core.BNCreateDataRenderer(self._cb)
@staticmethod
@@ -145,7 +146,7 @@ class DataRenderer:
result = self.perform_get_lines_for_data(ctxt, view, addr, type, prefixTokens, width, pycontext)
count[0] = len(result)
- line_buf = (core.BNDisassemblyTextLine * len(result))()
+ self.line_buf = (core.BNDisassemblyTextLine * len(result))()
for i in range(len(result)):
line = result[i]
color = line.highlight
@@ -154,27 +155,30 @@ class DataRenderer:
raise ValueError("Specified color is not one of HighlightStandardColor, highlight.HighlightColor")
if isinstance(color, enums.HighlightStandardColor):
color = highlight.HighlightColor(color)
- line_buf[i].highlight = color._to_core_struct()
+ self.line_buf[i].highlight = color._to_core_struct()
if line.address is None:
if len(line.tokens) > 0:
- line_buf[i].addr = line.tokens[0].address
+ self.line_buf[i].addr = line.tokens[0].address
else:
- line_buf[i].addr = 0
+ self.line_buf[i].addr = 0
else:
- line_buf[i].addr = line.address
+ self.line_buf[i].addr = line.address
if line.il_instruction is not None:
- line_buf[i].instrIndex = line.il_instruction.instr_index
+ self.line_buf[i].instrIndex = line.il_instruction.instr_index
else:
- line_buf[i].instrIndex = 0xffffffffffffffff
+ self.line_buf[i].instrIndex = 0xffffffffffffffff
- line_buf[i].count = len(line.tokens)
- line_buf[i].tokens = function.InstructionTextToken._get_core_struct(line.tokens)
+ self.line_buf[i].count = len(line.tokens)
+ self.line_buf[i].tokens = function.InstructionTextToken._get_core_struct(line.tokens)
- return ctypes.cast(line_buf, ctypes.c_void_p).value
+ return ctypes.cast(self.line_buf, ctypes.c_void_p).value
except:
log_error(traceback.format_exc())
return None
+ def _free_lines(self, ctxt, lines, count):
+ self.line_buf = None
+
def perform_free_object(self, ctxt):
pass
diff --git a/relocationhandler.cpp b/relocationhandler.cpp
index 045e9fa6..b25b0f65 100644
--- a/relocationhandler.cpp
+++ b/relocationhandler.cpp
@@ -139,6 +139,7 @@ bool CoreRelocationHandler::GetRelocationInfo(
BNRelocationHandlerGetRelocationInfo(m_object, view->GetObject(), arch->GetObject(), results, result.size());
for (size_t i = 0; i < result.size(); i++)
result[i] = results[i];
+ delete[] results;
return status;
}
diff --git a/type.cpp b/type.cpp
index 0e686a0a..4ecbc338 100644
--- a/type.cpp
+++ b/type.cpp
@@ -1909,6 +1909,7 @@ TypeBuilder& TypeBuilder::SetParameters(const std::vector<FunctionParameter>& pa
size_t paramCount = 0;
BNFunctionParameter* paramArray = GetParamArray(params, paramCount);
BNSetFunctionTypeBuilderParameters(m_object, paramArray, paramCount);
+ delete[] paramArray;
return *this;
}