Skip to content

Commit 6955825

Browse files
committed
Add importDependencies argument to ParseTypeString to control library imports
1 parent 6320364 commit 6955825

File tree

6 files changed

+143
-30
lines changed

6 files changed

+143
-30
lines changed

binaryninjaapi.h

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5858,11 +5858,12 @@ namespace BinaryNinja {
58585858
\param[in] text Text containing the type definition
58595859
\param[out] result Reference into which the resulting type and name will be written
58605860
\param[out] errors Reference to a list into which any parse errors will be written
5861-
\param typesAllowRedefinition
5861+
\param[in] typesAllowRedefinition List of types whose names are allowed to be overwritten (legacy cruft?)
5862+
\param[in] importDependencies If Type Library / Type Archive types should be imported during parsing
58625863
\return Whether parsing was successful
58635864
*/
58645865
bool ParseTypeString(const std::string& text, QualifiedNameAndType& result, std::string& errors,
5865-
const std::set<QualifiedName>& typesAllowRedefinition = {});
5866+
const std::set<QualifiedName>& typesAllowRedefinition = {}, bool importDependencies = true);
58665867

58675868
/*! Parse an entire block of source into types, variables, and functions
58685869

@@ -5871,14 +5872,25 @@ namespace BinaryNinja {
58715872
\param[out] variables Reference to a list of QualifiedNames and Types the parsed variables will be writen to
58725873
\param[out] functions Reference to a list of QualifiedNames and Types the parsed functions will be writen to
58735874
\param[out] errors Reference to a list into which any parse errors will be written
5874-
\param typesAllowRedefinition
5875+
\param[in] typesAllowRedefinition List of types whose names are allowed to be overwritten (legacy cruft?)
5876+
\param[in] importDependencies If Type Library / Type Archive types should be imported during parsing
58755877
\return Whether parsing was successful
58765878
*/
58775879
bool ParseTypeString(const std::string& text, std::map<QualifiedName, Ref<Type>>& types,
58785880
std::map<QualifiedName, Ref<Type>>& variables, std::map<QualifiedName, Ref<Type>>& functions,
5879-
std::string& errors, const std::set<QualifiedName>& typesAllowRedefinition = {});
5881+
std::string& errors, const std::set<QualifiedName>& typesAllowRedefinition = {}, bool importDependencies = true);
5882+
5883+
/*! Parse an entire block of source into a structure containing types, variables, and functions
5884+
5885+
\param[in] text Source code to parse
5886+
\param[out] result Reference to a TypeParserResult structure into which types, variables, and functions will be written
5887+
\param[out] errors Reference to a list into which any parse errors will be written
5888+
\param[in] typesAllowRedefinition List of types whose names are allowed to be overwritten (legacy cruft?)
5889+
\param[in] importDependencies If Type Library / Type Archive types should be imported during parsing
5890+
\return Whether parsing was successful
5891+
*/
58805892
bool ParseTypesFromSource(const std::string& text, const std::vector<std::string>& options, const std::vector<std::string>& includeDirs, TypeParserResult& result,
5881-
std::string& errors, const std::set<QualifiedName>& typesAllowRedefinition = {});
5893+
std::string& errors, const std::set<QualifiedName>& typesAllowRedefinition = {}, bool importDependencies = true);
58825894

58835895
/*! Type Container for all types (user and auto) in the BinaryView. Any auto types
58845896
modified through the Type Container will be converted into user types.
@@ -17287,10 +17299,21 @@ namespace BinaryNinja {
1728717299
with knowledge of the types in the Type Container.
1728817300

1728917301
\param source Source code to parse
17302+
\param importDependencies If Type Library / Type Archive types should be imported during parsing
1729017303
\param result Reference into which the resulting type and name will be written
1729117304
\param errors Reference to a list into which any parse errors will be written
1729217305
\return True if parsing was successful
1729317306
*/
17307+
bool ParseTypeString(
17308+
const std::string& source,
17309+
bool importDependencies,
17310+
QualifiedNameAndType& result,
17311+
std::vector<TypeParserError>& errors
17312+
);
17313+
17314+
/*!
17315+
\deprecated Use `ParseTypeString` with the extra `importDependencies` param
17316+
*/
1729417317
bool ParseTypeString(
1729517318
const std::string& source,
1729617319
QualifiedNameAndType& result,
@@ -17305,10 +17328,25 @@ namespace BinaryNinja {
1730517328
\param options Optional string arguments to pass as options, e.g. command line arguments
1730617329
\param includeDirs Optional list of directories to include in the header search path
1730717330
\param autoTypeSource Optional source of types if used for automatically generated types
17331+
\param importDependencies If Type Library / Type Archive types should be imported during parsing
1730817332
\param result Reference to structure into which the results will be written
1730917333
\param errors Reference to a list into which any parse errors will be written
1731017334
\return True if successful
1731117335
*/
17336+
bool ParseTypesFromSource(
17337+
const std::string& text,
17338+
const std::string& fileName,
17339+
const std::vector<std::string>& options,
17340+
const std::vector<std::string>& includeDirs,
17341+
const std::string& autoTypeSource,
17342+
bool importDependencies,
17343+
TypeParserResult& result,
17344+
std::vector<TypeParserError>& errors
17345+
);
17346+
17347+
/*!
17348+
\deprecated Use `ParseTypesFromSource` with the extra `importDependencies` param
17349+
*/
1731217350
bool ParseTypesFromSource(
1731317351
const std::string& text,
1731417352
const std::string& fileName,

binaryninjacore.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4662,10 +4662,10 @@ extern "C"
46624662
BINARYNINJACOREAPI bool BNGetDataVariableAtAddress(BNBinaryView* view, uint64_t addr, BNDataVariable* var);
46634663

46644664
BINARYNINJACOREAPI bool BNParseTypeString(BNBinaryView* view, const char* text, BNQualifiedNameAndType* result,
4665-
char** errors, BNQualifiedNameList* typesAllowRedefinition);
4665+
char** errors, BNQualifiedNameList* typesAllowRedefinition, bool importDepencencies);
46664666
BINARYNINJACOREAPI bool BNParseTypesString(BNBinaryView* view, const char* text, const char* const* options, size_t optionCount,
46674667
const char* const* includeDirs, size_t includeDirCount, BNTypeParserResult* result, char** errors,
4668-
BNQualifiedNameList* typesAllowRedefinition);
4668+
BNQualifiedNameList* typesAllowRedefinition, bool importDepencencies);
46694669
BINARYNINJACOREAPI void BNFreeQualifiedNameAndType(BNQualifiedNameAndType* obj);
46704670
BINARYNINJACOREAPI void BNFreeQualifiedNameAndTypeArray(BNQualifiedNameAndType* obj, size_t count);
46714671
BINARYNINJACOREAPI void BNFreeQualifiedNameTypeAndId(BNQualifiedNameTypeAndId* obj);
@@ -4746,14 +4746,14 @@ extern "C"
47464746
BINARYNINJACOREAPI bool BNTypeContainerGetTypeNames(BNTypeContainer* container, BNQualifiedName** typeNames, size_t* count);
47474747
BINARYNINJACOREAPI bool BNTypeContainerGetTypeNamesAndIds(BNTypeContainer* container, char*** typeIds, BNQualifiedName** typeNames, size_t* count);
47484748
BINARYNINJACOREAPI bool BNTypeContainerParseTypeString(BNTypeContainer* container,
4749-
const char* source, BNQualifiedNameAndType* result,
4749+
const char* source, bool importDepencencies, BNQualifiedNameAndType* result,
47504750
BNTypeParserError** errors, size_t* errorCount
47514751
);
47524752
BINARYNINJACOREAPI bool BNTypeContainerParseTypesFromSource(BNTypeContainer* container,
47534753
const char* source, const char* fileName,
47544754
const char* const* options, size_t optionCount,
47554755
const char* const* includeDirs, size_t includeDirCount,
4756-
const char* autoTypeSource, BNTypeParserResult* result,
4756+
const char* autoTypeSource, bool importDepencencies, BNTypeParserResult* result,
47574757
BNTypeParserError** errors, size_t* errorCount
47584758
);
47594759

binaryview.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3717,7 +3717,7 @@ bool BinaryView::ParsePossibleValueSet(
37173717

37183718

37193719
bool BinaryView::ParseTypeString(const string& text, QualifiedNameAndType& result, string& errors,
3720-
const std::set<QualifiedName>& typesAllowRedefinition)
3720+
const std::set<QualifiedName>& typesAllowRedefinition, bool importDependencies)
37213721
{
37223722
BNQualifiedNameAndType nt;
37233723
char* errorStr;
@@ -3732,7 +3732,7 @@ bool BinaryView::ParseTypeString(const string& text, QualifiedNameAndType& resul
37323732
i++;
37333733
}
37343734

3735-
if (!BNParseTypeString(m_object, text.c_str(), &nt, &errorStr, &typesList))
3735+
if (!BNParseTypeString(m_object, text.c_str(), &nt, &errorStr, &typesList, importDependencies))
37363736
{
37373737
errors = errorStr;
37383738
BNFreeString(errorStr);
@@ -3751,7 +3751,7 @@ bool BinaryView::ParseTypeString(const string& text, QualifiedNameAndType& resul
37513751

37523752
bool BinaryView::ParseTypeString(const string& source, map<QualifiedName, Ref<Type>>& types,
37533753
map<QualifiedName, Ref<Type>>& variables, map<QualifiedName, Ref<Type>>& functions, string& errors,
3754-
const std::set<QualifiedName>& typesAllowRedefinition)
3754+
const std::set<QualifiedName>& typesAllowRedefinition, bool importDependencies)
37553755
{
37563756
BNTypeParserResult result;
37573757
char* errorStr = nullptr;
@@ -3774,7 +3774,7 @@ bool BinaryView::ParseTypeString(const string& source, map<QualifiedName, Ref<Ty
37743774
vector<const char*> includeDirs;
37753775

37763776
bool ok = BNParseTypesString(m_object, source.c_str(), options.data(), options.size(),
3777-
includeDirs.data(), includeDirs.size(), &result, &errorStr, &typesList);
3777+
includeDirs.data(), includeDirs.size(), &result, &errorStr, &typesList, importDependencies);
37783778
if (errorStr)
37793779
{
37803780
errors = errorStr;
@@ -3805,7 +3805,7 @@ bool BinaryView::ParseTypeString(const string& source, map<QualifiedName, Ref<Ty
38053805

38063806

38073807
bool BinaryView::ParseTypesFromSource(const string& source, const vector<string>& options, const vector<string>& includeDirs,
3808-
TypeParserResult& result, string& errors, const std::set<QualifiedName>& typesAllowRedefinition)
3808+
TypeParserResult& result, string& errors, const std::set<QualifiedName>& typesAllowRedefinition, bool importDependencies)
38093809
{
38103810
BNQualifiedNameList typesList;
38113811
typesList.count = typesAllowRedefinition.size();
@@ -3829,7 +3829,7 @@ bool BinaryView::ParseTypesFromSource(const string& source, const vector<string>
38293829
char* errorStr = nullptr;
38303830

38313831
bool ok = BNParseTypesString(m_object, source.c_str(), coreOptions.data(), coreOptions.size(),
3832-
coreIncludeDirs.data(), coreIncludeDirs.size(), &apiResult, &errorStr, &typesList);
3832+
coreIncludeDirs.data(), coreIncludeDirs.size(), &apiResult, &errorStr, &typesList, importDependencies);
38333833
if (errorStr)
38343834
{
38353835
errors = errorStr;

python/binaryview.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7026,14 +7026,15 @@ def __iter__(self):
70267026

70277027
return iter(LinearDisassemblyIterator(self, settings))
70287028

7029-
def parse_type_string(self, text: str) -> Tuple['_types.Type', '_types.QualifiedName']:
7029+
def parse_type_string(self, text: str, import_dependencies: bool = True) -> Tuple['_types.Type', '_types.QualifiedName']:
70307030
"""
70317031
``parse_type_string`` parses string containing C into a single type :py:class:`Type`.
70327032
In contrast to the :py:func:`~binaryninja.platform.Platform.parse_types_from_source` or :py:func:`~binaryninja.platform.Platform.parse_types_from_source_file`, ``parse_type_string``
70337033
can only load a single type, though it can take advantage of existing type information in the binary
70347034
view, while those two APIs do not.
70357035
70367036
:param str text: C source code string of type to create
7037+
:param import_dependencies: If Type Library / Type Archive types should be imported during parsing
70377038
:return: A tuple of a :py:class:`Type` and type name
70387039
:rtype: tuple(Type, QualifiedName)
70397040
:Example:
@@ -7050,7 +7051,7 @@ def parse_type_string(self, text: str) -> Tuple['_types.Type', '_types.Qualified
70507051
errors = ctypes.c_char_p()
70517052
type_list = core.BNQualifiedNameList()
70527053
type_list.count = 0
7053-
if not core.BNParseTypeString(self.handle, text, result, errors, type_list):
7054+
if not core.BNParseTypeString(self.handle, text, result, errors, type_list, import_dependencies):
70547055
assert errors.value is not None, "core.BNParseTypeString returned 'errors' set to None"
70557056
error_str = errors.value.decode("utf-8")
70567057
core.free_string(errors)
@@ -7061,7 +7062,7 @@ def parse_type_string(self, text: str) -> Tuple['_types.Type', '_types.Qualified
70617062
finally:
70627063
core.BNFreeQualifiedNameAndType(result)
70637064

7064-
def parse_types_from_string(self, text: str, options: Optional[List[str]] = None, include_dirs: Optional[List[str]] = None) -> '_types.TypeParserResult':
7065+
def parse_types_from_string(self, text: str, options: Optional[List[str]] = None, include_dirs: Optional[List[str]] = None, import_dependencies: bool = True) -> '_types.TypeParserResult':
70657066
"""
70667067
``parse_types_from_string`` parses string containing C into a :py:class:`TypeParserResult` objects. This API
70677068
unlike the :py:func:`~binaryninja.platform.Platform.parse_types_from_source` allows the reference of types already defined
@@ -7070,6 +7071,7 @@ def parse_types_from_string(self, text: str, options: Optional[List[str]] = None
70707071
:param str text: C source code string of types, variables, and function types, to create
70717072
:param options: Optional list of string options to be passed into the type parser
70727073
:param include_dirs: Optional list of header search directories
7074+
:param import_dependencies: If Type Library / Type Archive types should be imported during parsing
70737075
:return: :py:class:`~binaryninja.typeparser.TypeParserResult` (a SyntaxError is thrown on parse error)
70747076
:rtype: TypeParserResult
70757077
:Example:
@@ -7102,7 +7104,7 @@ def parse_types_from_string(self, text: str, options: Optional[List[str]] = None
71027104
type_list.count = 0
71037105
if not core.BNParseTypesString(
71047106
self.handle, text, options_cpp, len(options), include_dirs_cpp,
7105-
len(include_dirs), parse, errors, type_list):
7107+
len(include_dirs), parse, errors, type_list, import_dependencies):
71067108
assert errors.value is not None, "core.BNParseTypesString returned errors set to None"
71077109
error_str = errors.value.decode("utf-8")
71087110
core.free_string(errors)
@@ -7170,7 +7172,7 @@ def parse_possiblevalueset(
71707172
value = ''
71717173
if not core.BNParsePossibleValueSet(self.handle, value, state, result, here, errors):
71727174
if errors:
7173-
assert errors.value is not None, "core.BNParseTypesString returned errors set to None"
7175+
assert errors.value is not None, "core.BNParsePossibleValueSet returned errors set to None"
71747176
error_str = errors.value.decode("utf-8")
71757177
else:
71767178
error_str = "Error parsing specified PossibleValueSet"

python/typecontainer.py

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,9 +300,46 @@ def type_names_and_ids(self) -> Optional[Mapping[str, '_types.QualifiedName']]:
300300
core.BNFreeStringList(result_ids, result_count.value)
301301
return result
302302

303+
def parse_type_string(
304+
self, source: str, import_dependencies: bool = True
305+
) -> Tuple[Optional[Tuple['_types.QualifiedNameType', '_types.Type']], List['typeparser.TypeParserError']]:
306+
"""
307+
Parse a single type and name from a string containing their definition, with
308+
knowledge of the types in the Type Container.
309+
310+
:param source: Source code to parse
311+
:param import_dependencies: If Type Library / Type Archive types should be imported during parsing
312+
:return: A tuple of (result, errors) where result is a tuple of (type, name) or
313+
None of there was a fatal error.
314+
"""
315+
result_cpp = core.BNQualifiedNameAndType()
316+
errors_cpp = ctypes.POINTER(core.BNTypeParserError)()
317+
error_count = ctypes.c_size_t()
318+
319+
success = core.BNTypeContainerParseTypeString(
320+
self.handle, source, import_dependencies, result_cpp, errors_cpp, error_count
321+
)
322+
323+
if success:
324+
result = (
325+
_types.QualifiedName._from_core_struct(result_cpp.name),
326+
_types.Type.create(handle=core.BNNewTypeReference(result_cpp.type))
327+
)
328+
core.BNFreeQualifiedNameAndType(result_cpp)
329+
else:
330+
result = None
331+
core.BNFreeTypeParserResult(result_cpp)
332+
333+
errors = []
334+
for i in range(error_count.value):
335+
errors.append(typeparser.TypeParserError._from_core_struct(errors_cpp[i]))
336+
core.BNFreeTypeParserErrors(errors_cpp, error_count.value)
337+
338+
return result, errors
339+
303340
def parse_types_from_source(self, source: str, file_name: str,
304341
options: Optional[List[str]] = None, include_dirs: Optional[List[str]] = None,
305-
auto_type_source: str = ""
342+
auto_type_source: str = "", import_dependencies: bool = True
306343
) -> Tuple[Optional['typeparser.TypeParserResult'], List['typeparser.TypeParserError']]:
307344
"""
308345
Parse an entire block of source into types, variables, and functions, with
@@ -313,6 +350,7 @@ def parse_types_from_source(self, source: str, file_name: str,
313350
:param options: Optional string arguments to pass as options, e.g. command line arguments
314351
:param include_dirs: Optional list of directories to include in the header search path
315352
:param auto_type_source: Optional source of types if used for automatically generated types
353+
:param import_dependencies: If Type Library / Type Archive types should be imported during parsing
316354
:return: A tuple of (result, errors) where the result is None if there was a fatal error
317355
"""
318356
if options is None:
@@ -335,7 +373,7 @@ def parse_types_from_source(self, source: str, file_name: str,
335373
success = core.BNTypeContainerParseTypesFromSource(
336374
self.handle, source, file_name,
337375
options_cpp, len(options),
338-
include_dirs_cpp, len(include_dirs), auto_type_source,
376+
include_dirs_cpp, len(include_dirs), auto_type_source, import_dependencies,
339377
result_cpp, errors_cpp, error_count
340378
)
341379

typecontainer.cpp

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ std::optional<std::unordered_map<std::string, QualifiedName>> TypeContainer::Get
331331

332332
bool TypeContainer::ParseTypeString(
333333
const std::string& source,
334+
bool importDependencies,
334335
BinaryNinja::QualifiedNameAndType& result,
335336
std::vector<TypeParserError>& errors
336337
)
@@ -339,7 +340,7 @@ bool TypeContainer::ParseTypeString(
339340
BNTypeParserError* apiErrors;
340341
size_t errorCount;
341342

342-
auto success = BNTypeContainerParseTypeString(m_object, source.c_str(), &apiResult,
343+
auto success = BNTypeContainerParseTypeString(m_object, source.c_str(), importDependencies, &apiResult,
343344
&apiErrors, &errorCount);
344345

345346
for (size_t j = 0; j < errorCount; j ++)
@@ -367,12 +368,23 @@ bool TypeContainer::ParseTypeString(
367368
}
368369

369370

371+
bool TypeContainer::ParseTypeString(
372+
const std::string& source,
373+
BinaryNinja::QualifiedNameAndType& result,
374+
std::vector<TypeParserError>& errors
375+
)
376+
{
377+
return ParseTypeString(source, true, result, errors);
378+
}
379+
380+
370381
bool TypeContainer::ParseTypesFromSource(
371382
const std::string& text,
372383
const std::string& fileName,
373384
const std::vector<std::string>& options,
374385
const std::vector<std::string>& includeDirs,
375386
const std::string& autoTypeSource,
387+
bool importDependencies,
376388
BinaryNinja::TypeParserResult& result,
377389
std::vector<TypeParserError>& errors
378390
)
@@ -393,8 +405,8 @@ bool TypeContainer::ParseTypesFromSource(
393405
size_t errorCount;
394406

395407
auto success = BNTypeContainerParseTypesFromSource(m_object, text.c_str(), fileName.c_str(),
396-
apiOptions, options.size(), apiIncludeDirs, includeDirs.size(), autoTypeSource.c_str(), &apiResult,
397-
&apiErrors, &errorCount);
408+
apiOptions, options.size(), apiIncludeDirs, includeDirs.size(), autoTypeSource.c_str(), importDependencies,
409+
&apiResult, &apiErrors, &errorCount);
398410

399411
delete [] apiOptions;
400412
delete [] apiIncludeDirs;
@@ -403,11 +415,11 @@ bool TypeContainer::ParseTypesFromSource(
403415
{
404416
TypeParserError error;
405417
error.severity = apiErrors[j].severity,
406-
error.message = apiErrors[j].message,
407-
error.fileName = apiErrors[j].fileName,
408-
error.line = apiErrors[j].line,
409-
error.column = apiErrors[j].column,
410-
errors.push_back(error);
418+
error.message = apiErrors[j].message,
419+
error.fileName = apiErrors[j].fileName,
420+
error.line = apiErrors[j].line,
421+
error.column = apiErrors[j].column,
422+
errors.push_back(error);
411423
}
412424
BNFreeTypeParserErrors(apiErrors, errorCount);
413425

@@ -449,3 +461,26 @@ bool TypeContainer::ParseTypesFromSource(
449461
BNFreeTypeParserResult(&apiResult);
450462
return true;
451463
}
464+
465+
466+
bool TypeContainer::ParseTypesFromSource(
467+
const std::string& text,
468+
const std::string& fileName,
469+
const std::vector<std::string>& options,
470+
const std::vector<std::string>& includeDirs,
471+
const std::string& autoTypeSource,
472+
BinaryNinja::TypeParserResult& result,
473+
std::vector<TypeParserError>& errors
474+
)
475+
{
476+
return ParseTypesFromSource(
477+
text,
478+
fileName,
479+
options,
480+
includeDirs,
481+
autoTypeSource,
482+
true,
483+
result,
484+
errors
485+
);
486+
}

0 commit comments

Comments
 (0)