Skip to content

Commit b546d0c

Browse files
committed
Fix partial initialization of DisassemblyTextLine
The usage of `DisassemblyTextLine` in the FFI was unsound, we would forget to initialize some fields causing a myriad of issues where round-tripping through the FFI was losing information.
1 parent 127ab74 commit b546d0c

File tree

10 files changed

+121
-366
lines changed

10 files changed

+121
-366
lines changed

architecture.cpp

Lines changed: 11 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <inttypes.h>
2525
#include <vector>
2626
#include "binaryninjaapi.h"
27+
#include "ffi.h"
2728

2829
using namespace BinaryNinja;
2930
using namespace std;
@@ -2441,17 +2442,7 @@ bool DisassemblyTextRenderer::GetInstructionText(uint64_t addr, size_t& len, vec
24412442
if (!BNGetDisassemblyTextRendererInstructionText(m_object, addr, &len, &result, &count))
24422443
return false;
24432444

2444-
for (size_t i = 0; i < count; i++)
2445-
{
2446-
DisassemblyTextLine line;
2447-
line.addr = result[i].addr;
2448-
line.instrIndex = result[i].instrIndex;
2449-
line.highlight = result[i].highlight;
2450-
line.tokens = InstructionTextToken::ConvertInstructionTextTokenList(result[i].tokens, result[i].count);
2451-
line.tags = Tag::ConvertTagList(result[i].tags, result[i].tagCount);
2452-
lines.push_back(line);
2453-
}
2454-
2445+
lines = ParseAPIObjectList<DisassemblyTextLine>(result, count);
24552446
BNFreeDisassemblyTextLines(result, count);
24562447
return true;
24572448
}
@@ -2460,41 +2451,15 @@ bool DisassemblyTextRenderer::GetInstructionText(uint64_t addr, size_t& len, vec
24602451
vector<DisassemblyTextLine> DisassemblyTextRenderer::PostProcessInstructionTextLines(
24612452
uint64_t addr, size_t len, const vector<DisassemblyTextLine>& lines, const string& indentSpaces)
24622453
{
2463-
BNDisassemblyTextLine* inLines = new BNDisassemblyTextLine[lines.size()];
2464-
for (size_t i = 0; i < lines.size(); i++)
2465-
{
2466-
inLines[i].addr = lines[i].addr;
2467-
inLines[i].instrIndex = lines[i].instrIndex;
2468-
inLines[i].highlight = lines[i].highlight;
2469-
inLines[i].tokens = InstructionTextToken::CreateInstructionTextTokenList(lines[i].tokens);
2470-
inLines[i].count = lines[i].tokens.size();
2471-
inLines[i].tags = Tag::CreateTagList(lines[i].tags, &inLines[i].tagCount);
2472-
}
2473-
2454+
size_t inCount = 0;
2455+
BNDisassemblyTextLine* inLines = AllocAPIObjectList<DisassemblyTextLine>(lines, &inCount);
24742456
BNDisassemblyTextLine* result = nullptr;
24752457
size_t count = 0;
24762458
result = BNPostProcessDisassemblyTextRendererLines(
2477-
m_object, addr, len, inLines, lines.size(), &count, indentSpaces.c_str());
2478-
2479-
for (size_t i = 0; i < lines.size(); i++)
2480-
{
2481-
InstructionTextToken::FreeInstructionTextTokenList(inLines[i].tokens, inLines[i].count);
2482-
Tag::FreeTagList(inLines[i].tags, inLines[i].tagCount);
2483-
}
2484-
delete[] inLines;
2485-
2486-
vector<DisassemblyTextLine> outLines;
2487-
for (size_t i = 0; i < count; i++)
2488-
{
2489-
DisassemblyTextLine line;
2490-
line.addr = result[i].addr;
2491-
line.instrIndex = result[i].instrIndex;
2492-
line.highlight = result[i].highlight;
2493-
line.tokens = InstructionTextToken::ConvertInstructionTextTokenList(result[i].tokens, result[i].count);
2494-
line.tags = Tag::ConvertTagList(result[i].tags, result[i].tagCount);
2495-
outLines.push_back(line);
2496-
}
2459+
m_object, addr, len, inLines, inCount, &count, indentSpaces.c_str());
24972460

2461+
vector<DisassemblyTextLine> outLines = ParseAPIObjectList<DisassemblyTextLine>(result, count);
2462+
FreeAPIObjectList<DisassemblyTextLine>(inLines, inCount);
24982463
BNFreeDisassemblyTextLines(result, count);
24992464
return outLines;
25002465
}
@@ -2507,17 +2472,7 @@ bool DisassemblyTextRenderer::GetDisassemblyText(uint64_t addr, size_t& len, vec
25072472
if (!BNGetDisassemblyTextRendererLines(m_object, addr, &len, &result, &count))
25082473
return false;
25092474

2510-
for (size_t i = 0; i < count; i++)
2511-
{
2512-
DisassemblyTextLine line;
2513-
line.addr = result[i].addr;
2514-
line.instrIndex = result[i].instrIndex;
2515-
line.highlight = result[i].highlight;
2516-
line.tokens = InstructionTextToken::ConvertInstructionTextTokenList(result[i].tokens, result[i].count);
2517-
line.tags = Tag::ConvertTagList(result[i].tags, result[i].tagCount);
2518-
lines.push_back(line);
2519-
}
2520-
2475+
lines = ParseAPIObjectList<DisassemblyTextLine>(result, count);
25212476
BNFreeDisassemblyTextLines(result, count);
25222477
return true;
25232478
}
@@ -2614,31 +2569,14 @@ void DisassemblyTextRenderer::AddIntegerToken(
26142569
void DisassemblyTextRenderer::WrapComment(DisassemblyTextLine& line, vector<DisassemblyTextLine>& lines,
26152570
const string& comment, bool hasAutoAnnotations, const string& leadingSpaces, const string& indentSpaces)
26162571
{
2617-
BNDisassemblyTextLine inLine;
2618-
inLine.addr = line.addr;
2619-
inLine.instrIndex = line.instrIndex;
2620-
inLine.highlight = line.highlight;
2621-
inLine.count = line.tokens.size();
2622-
inLine.tokens = InstructionTextToken::CreateInstructionTextTokenList(line.tokens);
2623-
inLine.tags = Tag::CreateTagList(line.tags, &inLine.tagCount);
2624-
2572+
BNDisassemblyTextLine inLine = line.GetAPIObject();
26252573
size_t count = 0;
26262574
BNDisassemblyTextLine* result = BNDisassemblyTextRendererWrapComment(
26272575
m_object, &inLine, &count, comment.c_str(), hasAutoAnnotations, leadingSpaces.c_str(), indentSpaces.c_str());
26282576

2629-
for (size_t i = 0; i < count; i++)
2630-
{
2631-
DisassemblyTextLine line;
2632-
line.addr = result[i].addr;
2633-
line.instrIndex = result[i].instrIndex;
2634-
line.highlight = result[i].highlight;
2635-
line.tokens = InstructionTextToken::ConvertInstructionTextTokenList(result[i].tokens, result[i].count);
2636-
line.tags = Tag::ConvertTagList(result[i].tags, result[i].tagCount);
2637-
lines.push_back(line);
2638-
}
2639-
2577+
lines = ParseAPIObjectList<DisassemblyTextLine>(result, count);
26402578
BNFreeDisassemblyTextLines(result, count);
2641-
BNFreeInstructionText(inLine.tokens, inLine.count);
2579+
DisassemblyTextLine::FreeAPIObject(&inLine);
26422580
}
26432581

26442582

basicblock.cpp

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
// IN THE SOFTWARE.
2020

2121
#include "binaryninjaapi.h"
22+
#include "ffi.h"
2223

2324
using namespace BinaryNinja;
2425
using namespace std;
@@ -143,6 +144,34 @@ void DisassemblySettings::SetCallParameterHints(BNDisassemblyCallParameterHints
143144
}
144145

145146

147+
BNDisassemblyTextLineTypeInfo DisassemblyTextLineTypeInfo::GetAPIObject() const
148+
{
149+
BNDisassemblyTextLineTypeInfo result;
150+
result.hasTypeInfo = this->hasTypeInfo;
151+
result.parentType = this->parentType ? BNNewTypeReference(this->parentType->GetObject()) : nullptr;
152+
result.fieldIndex = this->fieldIndex;
153+
result.offset = this->offset;
154+
return result;
155+
}
156+
157+
158+
void DisassemblyTextLineTypeInfo::FreeAPIObject(BNDisassemblyTextLineTypeInfo *value)
159+
{
160+
BNFreeType(value->parentType);
161+
}
162+
163+
164+
DisassemblyTextLineTypeInfo DisassemblyTextLineTypeInfo::FromAPIObject(const BNDisassemblyTextLineTypeInfo *value)
165+
{
166+
DisassemblyTextLineTypeInfo result;
167+
result.hasTypeInfo = value->hasTypeInfo;
168+
result.fieldIndex = value->fieldIndex;
169+
result.parentType = value->parentType ? new Type(BNNewTypeReference(value->parentType)) : nullptr;
170+
result.offset = value->offset;
171+
return result;
172+
}
173+
174+
146175
DisassemblyTextLine::DisassemblyTextLine()
147176
{
148177
addr = 0;
@@ -162,6 +191,41 @@ DisassemblyTextLine::DisassemblyTextLine()
162191
}
163192

164193

194+
BNDisassemblyTextLine DisassemblyTextLine::GetAPIObject() const
195+
{
196+
BNDisassemblyTextLine result;
197+
result.addr = this->addr;
198+
result.instrIndex = this->instrIndex;
199+
result.highlight = this->highlight;
200+
result.tokens = InstructionTextToken::CreateInstructionTextTokenList(this->tokens);
201+
result.count = this->tokens.size();
202+
result.tags = Tag::CreateTagList(this->tags, &(result.tagCount));
203+
result.typeInfo = this->typeInfo.GetAPIObject();
204+
return result;
205+
}
206+
207+
208+
void DisassemblyTextLine::FreeAPIObject(BNDisassemblyTextLine *value)
209+
{
210+
InstructionTextToken::FreeInstructionTextTokenList(value->tokens, value->count);
211+
Tag::FreeTagList(value->tags, value->tagCount);
212+
DisassemblyTextLineTypeInfo::FreeAPIObject(&value->typeInfo);
213+
}
214+
215+
216+
DisassemblyTextLine DisassemblyTextLine::FromAPIObject(const BNDisassemblyTextLine *value)
217+
{
218+
DisassemblyTextLine result;
219+
result.addr = value->addr;
220+
result.instrIndex = value->instrIndex;
221+
result.highlight = value->highlight;
222+
result.tokens = InstructionTextToken::ConvertInstructionTextTokenList(value->tokens, value->count);
223+
result.tags = Tag::ConvertTagList(value->tags, value->tagCount);
224+
result.typeInfo = DisassemblyTextLineTypeInfo::FromAPIObject(&value->typeInfo);
225+
return result;
226+
}
227+
228+
165229
size_t DisassemblyTextLine::GetTotalWidth() const
166230
{
167231
size_t result = 0;
@@ -435,19 +499,7 @@ vector<DisassemblyTextLine> BasicBlock::GetDisassemblyText(DisassemblySettings*
435499
size_t count;
436500
BNDisassemblyTextLine* lines = BNGetBasicBlockDisassemblyText(m_object, settings->GetObject(), &count);
437501

438-
vector<DisassemblyTextLine> result;
439-
result.reserve(count);
440-
for (size_t i = 0; i < count; i++)
441-
{
442-
DisassemblyTextLine line;
443-
line.addr = lines[i].addr;
444-
line.instrIndex = lines[i].instrIndex;
445-
line.highlight = lines[i].highlight;
446-
line.tokens = InstructionTextToken::ConvertInstructionTextTokenList(lines[i].tokens, lines[i].count);
447-
line.tags = Tag::ConvertTagList(lines[i].tags, lines[i].tagCount);
448-
result.push_back(line);
449-
}
450-
502+
vector<DisassemblyTextLine> result = ParseAPIObjectList<DisassemblyTextLine>(lines, count);;
451503
BNFreeDisassemblyTextLines(lines, count);
452504
return result;
453505
}

binaryninjaapi.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4045,10 +4045,14 @@ namespace BinaryNinja {
40454045
struct DisassemblyTextLineTypeInfo
40464046
{
40474047
bool hasTypeInfo;
4048-
BinaryNinja::Ref<BinaryNinja::Type> parentType;
4048+
Ref<Type> parentType;
40494049
size_t fieldIndex;
40504050
uint64_t offset;
40514051

4052+
BNDisassemblyTextLineTypeInfo GetAPIObject() const;
4053+
static void FreeAPIObject(BNDisassemblyTextLineTypeInfo* value);
4054+
static DisassemblyTextLineTypeInfo FromAPIObject(const BNDisassemblyTextLineTypeInfo* value);
4055+
40524056
DisassemblyTextLineTypeInfo() : hasTypeInfo(false), parentType(nullptr), fieldIndex(-1), offset(0) {}
40534057
};
40544058

@@ -4063,6 +4067,10 @@ namespace BinaryNinja {
40634067

40644068
DisassemblyTextLine();
40654069

4070+
BNDisassemblyTextLine GetAPIObject() const;
4071+
static void FreeAPIObject(BNDisassemblyTextLine* value);
4072+
static DisassemblyTextLine FromAPIObject(const BNDisassemblyTextLine* value);
4073+
40664074
size_t GetTotalWidth() const;
40674075
size_t GetAddressAndIndentationWidth() const;
40684076
std::vector<InstructionTextToken> GetAddressAndIndentationTokens() const;

datarenderer.cpp

Lines changed: 6 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "binaryninjaapi.h"
2+
#include "ffi.h"
23

34
using namespace std;
45
using namespace BinaryNinja;
@@ -82,22 +83,10 @@ BNDisassemblyTextLine* DataRenderer::GetLinesForDataCallback(void* ctxt, BNBinar
8283
}
8384
auto lines = renderer->GetLinesForData(viewObj, addr, typeObj, prefixes, width, context,
8485
language ? language : string());
85-
*count = lines.size();
86-
BNDisassemblyTextLine* buf = new BNDisassemblyTextLine[lines.size()];
87-
for (size_t i = 0; i < lines.size(); i++)
88-
{
89-
const DisassemblyTextLine& line = lines[i];
90-
buf[i].addr = line.addr;
91-
buf[i].instrIndex = line.instrIndex;
92-
buf[i].highlight = line.highlight;
93-
buf[i].tokens = InstructionTextToken::CreateInstructionTextTokenList(line.tokens);
94-
buf[i].count = line.tokens.size();
95-
buf[i].tags = Tag::CreateTagList(line.tags, &(buf[i].tagCount));
96-
}
97-
86+
BNDisassemblyTextLine* result = AllocAPIObjectList(lines, count);
9887
for (size_t i = 0; i < ctxCount; i++)
9988
context[i].first->Release();
100-
return buf;
89+
return result;
10190
}
10291

10392

@@ -110,12 +99,7 @@ void DataRenderer::FreeCallback(void* ctxt)
11099

111100
void DataRenderer::FreeLinesCallback(void* ctxt, BNDisassemblyTextLine* lines, size_t count)
112101
{
113-
for (size_t i = 0; i < count; i++)
114-
{
115-
InstructionTextToken::FreeInstructionTextTokenList(lines[i].tokens, lines[i].count);
116-
Tag::FreeTagList(lines[i].tags, lines[i].tagCount);
117-
}
118-
delete[] lines;
102+
FreeAPIObjectList<DisassemblyTextLine>(lines, count);
119103
}
120104

121105

@@ -157,18 +141,7 @@ vector<DisassemblyTextLine> DataRenderer::GetLinesForData(BinaryView* data, uint
157141
}
158142
delete[] prefixes;
159143

160-
vector<DisassemblyTextLine> result;
161-
result.reserve(count);
162-
for (size_t i = 0; i < count; i++)
163-
{
164-
DisassemblyTextLine line;
165-
line.addr = lines[i].addr;
166-
line.instrIndex = lines[i].instrIndex;
167-
line.highlight = lines[i].highlight;
168-
line.tokens = InstructionTextToken::ConvertAndFreeInstructionTextTokenList(lines[i].tokens, lines[i].count);
169-
line.tags = Tag::ConvertAndFreeTagList(lines[i].tags, lines[i].tagCount);
170-
result.push_back(line);
171-
}
144+
vector<DisassemblyTextLine> result = ParseAPIObjectList<DisassemblyTextLine>(lines, count);
172145
BNFreeDisassemblyTextLines(lines, count);
173146
return result;
174147
}
@@ -199,19 +172,7 @@ vector<DisassemblyTextLine> DataRenderer::RenderLinesForData(BinaryView* data, u
199172
}
200173
delete[] prefixes;
201174

202-
vector<DisassemblyTextLine> result;
203-
result.reserve(count);
204-
for (size_t i = 0; i < count; i++)
205-
{
206-
DisassemblyTextLine line;
207-
line.addr = lines[i].addr;
208-
line.instrIndex = lines[i].instrIndex;
209-
line.highlight = lines[i].highlight;
210-
line.tokens = InstructionTextToken::ConvertAndFreeInstructionTextTokenList(lines[i].tokens, lines[i].count);
211-
line.tags = Tag::ConvertAndFreeTagList(lines[i].tags, lines[i].tagCount);
212-
result.push_back(line);
213-
}
214-
175+
vector<DisassemblyTextLine> result = ParseAPIObjectList<DisassemblyTextLine>(lines, count);
215176
BNFreeDisassemblyTextLines(lines, count);
216177
return result;
217178
}

0 commit comments

Comments
 (0)