Skip to content

Commit 6623d47

Browse files
committed
Pass platform to format string providers
1 parent 3012aa2 commit 6623d47

5 files changed

Lines changed: 155 additions & 46 deletions

binaryninjaapi.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20954,17 +20954,20 @@ namespace BinaryNinja {
2095420954
FormatStringResolutionProvider(BNFormatStringResolutionProvider* provider);
2095520955

2095620956
static bool IsValidCallback(
20957-
void* ctxt, const char* format, BNTypeWithConfidence** types, size_t* count);
20957+
void* ctxt, const char* format, BNPlatform* platform,
20958+
BNTypeWithConfidence** types, size_t* count);
2095820959
static void FreeTypeListCallback(void* ctxt, BNTypeWithConfidence* types, size_t count);
2095920960

2096020961
public:
2096120962
/*! Resolve the argument types described by a format string.
2096220963

2096320964
\param format Format string to validate and resolve
20965+
\param platform Platform whose ABI and C data model should be used to resolve types
2096420966
\return A list of argument types when valid, including an empty list for a valid format with no
2096520967
arguments, or an empty optional when invalid
2096620968
*/
20967-
virtual std::optional<std::vector<Confidence<Ref<Type>>>> IsValid(const std::string& format) = 0;
20969+
virtual std::optional<std::vector<Confidence<Ref<Type>>>> IsValid(
20970+
const std::string& format, Platform* platform) = 0;
2096820971

2096920972
std::string GetName() const;
2097020973
static std::vector<Ref<FormatStringResolutionProvider>> GetList();
@@ -20981,7 +20984,7 @@ namespace BinaryNinja {
2098120984
CoreFormatStringResolutionProvider(BNFormatStringResolutionProvider* provider);
2098220985

2098320986
virtual std::optional<std::vector<Confidence<Ref<Type>>>> IsValid(
20984-
const std::string& format) override;
20987+
const std::string& format, Platform* platform) override;
2098520988
};
2098620989

2098720990
/*! Components are objects that can contain Functions and other Components.

binaryninjacore.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3748,7 +3748,8 @@ extern "C"
37483748
typedef struct BNFormatStringResolutionProviderCallbacks
37493749
{
37503750
void* context;
3751-
bool (*isValid)(void* ctxt, const char* format, BNTypeWithConfidence** types, size_t* count);
3751+
bool (*isValid)(void* ctxt, const char* format, BNPlatform* platform,
3752+
BNTypeWithConfidence** types, size_t* count);
37523753
void (*freeTypeList)(void* ctxt, BNTypeWithConfidence* types, size_t count);
37533754
} BNFormatStringResolutionProviderCallbacks;
37543755

@@ -8745,7 +8746,7 @@ extern "C"
87458746
BINARYNINJACOREAPI char* BNGetFormatStringResolutionProviderName(
87468747
BNFormatStringResolutionProvider* provider);
87478748
BINARYNINJACOREAPI bool BNFormatStringResolutionProviderIsValid(
8748-
BNFormatStringResolutionProvider* provider, const char* format,
8749+
BNFormatStringResolutionProvider* provider, const char* format, BNPlatform* platform,
87498750
BNTypeWithConfidence** types, size_t* count);
87508751
BINARYNINJACOREAPI void BNFreeTypeWithConfidenceList(BNTypeWithConfidence* types, size_t count);
87518752

cstyleformatstringresolutionprovider.cpp

Lines changed: 135 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,54 @@ namespace
2929
ZeroPadFlag = 1 << 4
3030
};
3131

32+
bool IsWindowsPlatform(Platform* platform)
33+
{
34+
return platform && (platform->GetName().find("windows") != string::npos);
35+
}
36+
37+
bool IsApplePlatform(Platform* platform)
38+
{
39+
if (!platform)
40+
return false;
41+
const string name = platform->GetName();
42+
return name.starts_with("mac-") || name.starts_with("ios-") || name.starts_with("tvos-")
43+
|| name.starts_with("watchos-");
44+
}
45+
46+
optional<size_t> GetAddressSize(Platform* platform)
47+
{
48+
if (!platform)
49+
return nullopt;
50+
auto arch = platform->GetArchitecture();
51+
if (!arch)
52+
return nullopt;
53+
return arch->GetAddressSize();
54+
}
55+
56+
optional<size_t> GetPlatformTypeWidth(const string& name, Platform* platform)
57+
{
58+
auto addressSize = GetAddressSize(platform);
59+
if (!addressSize.has_value())
60+
return nullopt;
61+
62+
if ((name == "long") || (name == "unsigned long"))
63+
return IsWindowsPlatform(platform) ? 4 : *addressSize;
64+
if ((name == "ssize_t") || (name == "size_t") || (name == "ptrdiff_t")
65+
|| (name == "unsigned ptrdiff_t"))
66+
{
67+
return *addressSize;
68+
}
69+
if (name == "wchar_t")
70+
return IsWindowsPlatform(platform) ? 2 : 4;
71+
if (name == "long double")
72+
{
73+
if (IsWindowsPlatform(platform) || IsApplePlatform(platform))
74+
return 8;
75+
return *addressSize == 4 ? 12 : 16;
76+
}
77+
return nullopt;
78+
}
79+
3280
Confidence<Ref<Type>> IntegerArgument(
3381
size_t width, bool isSigned, uint8_t confidence = BN_FULL_CONFIDENCE,
3482
uint8_t signednessConfidence = BN_FULL_CONFIDENCE)
@@ -38,26 +86,32 @@ namespace
3886
}
3987

4088
Confidence<Ref<Type>> PlatformIntegerArgument(
41-
const string& name, bool isSigned, uint8_t confidence = BN_FULL_CONFIDENCE,
89+
Platform* platform, const string& name, bool isSigned, uint8_t confidence = BN_FULL_CONFIDENCE,
4290
uint8_t signednessConfidence = BN_FULL_CONFIDENCE)
4391
{
92+
auto width = GetPlatformTypeWidth(name, platform);
93+
if (!width.has_value())
94+
return nullptr;
4495
return Confidence<Ref<Type>>(
45-
Type::IntegerType(0, Confidence<bool>(isSigned, signednessConfidence), name), confidence);
96+
Type::IntegerType(*width, Confidence<bool>(isSigned, signednessConfidence)), confidence);
4697
}
4798

48-
Confidence<Ref<Type>> FloatArgument(size_t width, const string& name = "",
49-
uint8_t confidence = BN_FULL_CONFIDENCE)
99+
Confidence<Ref<Type>> FloatArgument(size_t width, uint8_t confidence = BN_FULL_CONFIDENCE)
50100
{
51-
return Confidence<Ref<Type>>(Type::FloatType(width, name), confidence);
101+
return Confidence<Ref<Type>>(Type::FloatType(width), confidence);
52102
}
53103

54104
Confidence<Ref<Type>> PointerArgument(
55-
const Confidence<Ref<Type>>& child, uint8_t confidence = BN_FULL_CONFIDENCE)
105+
Platform* platform, const Confidence<Ref<Type>>& child,
106+
uint8_t confidence = BN_FULL_CONFIDENCE)
56107
{
57-
return Confidence<Ref<Type>>(Type::PointerType(static_cast<size_t>(0), child), confidence);
108+
auto width = GetAddressSize(platform);
109+
if (!width.has_value() || !child.GetValue())
110+
return nullptr;
111+
return Confidence<Ref<Type>>(Type::PointerType(*width, child), confidence);
58112
}
59113

60-
Confidence<Ref<Type>> SignedIntegerArgument(LengthModifier length)
114+
Confidence<Ref<Type>> SignedIntegerArgument(LengthModifier length, Platform* platform)
61115
{
62116
switch (length)
63117
{
@@ -67,20 +121,20 @@ namespace
67121
// Signed char and signed short always promote to int.
68122
return IntegerArgument(4, true);
69123
case LengthModifier::L:
70-
return PlatformIntegerArgument("long", true);
124+
return PlatformIntegerArgument(platform, "long", true);
71125
case LengthModifier::LL:
72126
case LengthModifier::J:
73127
return IntegerArgument(8, true);
74128
case LengthModifier::Z:
75-
return PlatformIntegerArgument("ssize_t", true);
129+
return PlatformIntegerArgument(platform, "ssize_t", true);
76130
case LengthModifier::T:
77-
return PlatformIntegerArgument("ptrdiff_t", true);
131+
return PlatformIntegerArgument(platform, "ptrdiff_t", true);
78132
default:
79133
return nullptr;
80134
}
81135
}
82136

83-
Confidence<Ref<Type>> UnsignedIntegerArgument(LengthModifier length)
137+
Confidence<Ref<Type>> UnsignedIntegerArgument(LengthModifier length, Platform* platform)
84138
{
85139
switch (length)
86140
{
@@ -91,20 +145,20 @@ namespace
91145
// The promotion is int when it can represent every value, and unsigned int otherwise.
92146
return IntegerArgument(4, true, BN_HEURISTIC_CONFIDENCE, 0);
93147
case LengthModifier::L:
94-
return PlatformIntegerArgument("unsigned long", false);
148+
return PlatformIntegerArgument(platform, "unsigned long", false);
95149
case LengthModifier::LL:
96150
case LengthModifier::J:
97151
return IntegerArgument(8, false);
98152
case LengthModifier::Z:
99-
return PlatformIntegerArgument("size_t", false);
153+
return PlatformIntegerArgument(platform, "size_t", false);
100154
case LengthModifier::T:
101-
return PlatformIntegerArgument("unsigned ptrdiff_t", false);
155+
return PlatformIntegerArgument(platform, "unsigned ptrdiff_t", false);
102156
default:
103157
return nullptr;
104158
}
105159
}
106160

107-
Confidence<Ref<Type>> CountPointerArgument(LengthModifier length)
161+
Confidence<Ref<Type>> CountPointerArgument(LengthModifier length, Platform* platform)
108162
{
109163
Confidence<Ref<Type>> child;
110164
switch (length)
@@ -119,22 +173,39 @@ namespace
119173
child = IntegerArgument(2, true);
120174
break;
121175
case LengthModifier::L:
122-
child = PlatformIntegerArgument("long", true);
176+
child = PlatformIntegerArgument(platform, "long", true);
123177
break;
124178
case LengthModifier::LL:
125179
case LengthModifier::J:
126180
child = IntegerArgument(8, true);
127181
break;
128182
case LengthModifier::Z:
129-
child = PlatformIntegerArgument("ssize_t", true);
183+
child = PlatformIntegerArgument(platform, "ssize_t", true);
130184
break;
131185
case LengthModifier::T:
132-
child = PlatformIntegerArgument("ptrdiff_t", true);
186+
child = PlatformIntegerArgument(platform, "ptrdiff_t", true);
133187
break;
134188
default:
135189
return nullptr;
136190
}
137-
return PointerArgument(child);
191+
return PointerArgument(platform, child);
192+
}
193+
194+
Confidence<Ref<Type>> LongDoubleArgument(Platform* platform)
195+
{
196+
auto width = GetPlatformTypeWidth("long double", platform);
197+
if (!width.has_value())
198+
return nullptr;
199+
return FloatArgument(*width);
200+
}
201+
202+
bool AppendArgument(
203+
vector<Confidence<Ref<Type>>>& result, const Confidence<Ref<Type>>& argument)
204+
{
205+
if (!argument.GetValue())
206+
return false;
207+
result.push_back(argument);
208+
return true;
138209
}
139210

140211
bool ValidateFlags(char conversion, uint8_t flags)
@@ -214,7 +285,8 @@ namespace
214285
return true;
215286
}
216287

217-
optional<vector<Confidence<Ref<Type>>>> ResolveCStyleFormatString(const string& format)
288+
optional<vector<Confidence<Ref<Type>>>> ResolveCStyleFormatString(
289+
const string& format, Platform* platform)
218290
{
219291
vector<Confidence<Ref<Type>>> result;
220292
for (size_t i = 0; i < format.size(); i++)
@@ -319,13 +391,15 @@ namespace
319391
{
320392
case 'd':
321393
case 'i':
322-
result.push_back(SignedIntegerArgument(length));
394+
if (!AppendArgument(result, SignedIntegerArgument(length, platform)))
395+
return nullopt;
323396
break;
324397
case 'o':
325398
case 'u':
326399
case 'x':
327400
case 'X':
328-
result.push_back(UnsignedIntegerArgument(length));
401+
if (!AppendArgument(result, UnsignedIntegerArgument(length, platform)))
402+
return nullopt;
329403
break;
330404
case 'f':
331405
case 'F':
@@ -335,33 +409,57 @@ namespace
335409
case 'G':
336410
case 'a':
337411
case 'A':
338-
result.push_back(length == LengthModifier::CapitalL
339-
? FloatArgument(0, "long double") : FloatArgument(8));
412+
if (!AppendArgument(result, length == LengthModifier::CapitalL
413+
? LongDoubleArgument(platform) : FloatArgument(8)))
414+
{
415+
return nullopt;
416+
}
340417
break;
341418
case 'c':
342419
if (length == LengthModifier::L)
343-
result.push_back(IntegerArgument(4, true, BN_HEURISTIC_CONFIDENCE, 0));
420+
{
421+
if (!AppendArgument(
422+
result, IntegerArgument(4, true, BN_HEURISTIC_CONFIDENCE, 0)))
423+
{
424+
return nullopt;
425+
}
426+
}
344427
else
345-
result.push_back(IntegerArgument(4, true));
428+
{
429+
if (!AppendArgument(result, IntegerArgument(4, true)))
430+
return nullopt;
431+
}
346432
break;
347433
case 's':
348434
if (length == LengthModifier::L)
349435
{
350-
result.push_back(PointerArgument(
351-
Confidence<Ref<Type>>(Type::WideCharType(0, "wchar_t"), BN_FULL_CONFIDENCE)));
436+
auto width = GetPlatformTypeWidth("wchar_t", platform);
437+
if (!width.has_value() || !AppendArgument(result, PointerArgument(platform,
438+
Confidence<Ref<Type>>(
439+
Type::WideCharType(*width, "wchar_t"), BN_FULL_CONFIDENCE))))
440+
{
441+
return nullopt;
442+
}
352443
}
353444
else
354445
{
355-
result.push_back(PointerArgument(Confidence<Ref<Type>>(
356-
Type::IntegerType(1, Confidence<bool>(true, 0), "char"), BN_FULL_CONFIDENCE)));
446+
if (!AppendArgument(result, PointerArgument(platform, Confidence<Ref<Type>>(
447+
Type::IntegerType(1, Confidence<bool>(true, 0), "char"), BN_FULL_CONFIDENCE))))
448+
{
449+
return nullopt;
450+
}
357451
}
358452
break;
359453
case 'p':
360-
result.push_back(PointerArgument(
361-
Confidence<Ref<Type>>(Type::VoidType(), BN_FULL_CONFIDENCE)));
454+
if (!AppendArgument(result, PointerArgument(platform,
455+
Confidence<Ref<Type>>(Type::VoidType(), BN_FULL_CONFIDENCE))))
456+
{
457+
return nullopt;
458+
}
362459
break;
363460
case 'n':
364-
result.push_back(CountPointerArgument(length));
461+
if (!AppendArgument(result, CountPointerArgument(length, platform)))
462+
return nullopt;
365463
break;
366464
case '%':
367465
break;
@@ -379,9 +477,10 @@ CStyleFormatStringResolutionProvider::CStyleFormatStringResolutionProvider() :
379477
{}
380478

381479

382-
optional<vector<Confidence<Ref<Type>>>> CStyleFormatStringResolutionProvider::IsValid(const string& format)
480+
optional<vector<Confidence<Ref<Type>>>> CStyleFormatStringResolutionProvider::IsValid(
481+
const string& format, Platform* platform)
383482
{
384-
return ResolveCStyleFormatString(format);
483+
return ResolveCStyleFormatString(format, platform);
385484
}
386485

387486

cstyleformatstringresolutionprovider.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ namespace BinaryNinja
1414
CStyleFormatStringResolutionProvider();
1515

1616
std::optional<std::vector<Confidence<Ref<Type>>>> IsValid(
17-
const std::string& format) override;
17+
const std::string& format, Platform* platform) override;
1818
};
1919

2020
/*! Registers the built-in C-style format string provider if it is not already registered. */

formatstringresolutionprovider.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,14 @@ FormatStringResolutionProvider::FormatStringResolutionProvider(BNFormatStringRes
3434

3535

3636
bool FormatStringResolutionProvider::IsValidCallback(
37-
void* ctxt, const char* format, BNTypeWithConfidence** types, size_t* count)
37+
void* ctxt, const char* format, BNPlatform* platform,
38+
BNTypeWithConfidence** types, size_t* count)
3839
{
3940
FormatStringResolutionProvider* provider = (FormatStringResolutionProvider*)ctxt;
40-
auto result = provider->IsValid(format);
41+
Ref<Platform> resolvedPlatform;
42+
if (platform)
43+
resolvedPlatform = new CorePlatform(BNNewPlatformReference(platform));
44+
auto result = provider->IsValid(format, resolvedPlatform);
4145
if (!result.has_value())
4246
{
4347
*types = nullptr;
@@ -118,11 +122,13 @@ CoreFormatStringResolutionProvider::CoreFormatStringResolutionProvider(BNFormatS
118122
{}
119123

120124

121-
optional<vector<Confidence<Ref<Type>>>> CoreFormatStringResolutionProvider::IsValid(const string& format)
125+
optional<vector<Confidence<Ref<Type>>>> CoreFormatStringResolutionProvider::IsValid(
126+
const string& format, Platform* platform)
122127
{
123128
BNTypeWithConfidence* types = nullptr;
124129
size_t count = 0;
125-
if (!BNFormatStringResolutionProviderIsValid(m_object, format.c_str(), &types, &count))
130+
if (!BNFormatStringResolutionProviderIsValid(
131+
m_object, format.c_str(), platform ? platform->GetObject() : nullptr, &types, &count))
126132
return nullopt;
127133

128134
vector<Confidence<Ref<Type>>> result;

0 commit comments

Comments
 (0)