Skip to content

Commit 3602643

Browse files
committed
Fix memory leaks in the MachO Python API and create FatBinary
API Changes: LIEF::MachO::Parser won't return a 'std::vector' of MachO::Binary* but a pointer to MachO::FatBinary object It's a kind of wrapper on std::vector<MachO::Binary*>
1 parent 554fa15 commit 3602643

32 files changed

+431
-171
lines changed

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,8 @@ set(LIBFUZZER_SRC_FILES)
242242
if (LIEF_FUZZING)
243243
message(STATUS "Fuzzing Enabled")
244244

245-
set(LIBFUZZER_URL "http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer")
245+
set(LIBFUZZER_VERSION 314494)
246+
set(LIBFUZZER_URL "http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer/") #\?p=${LIBFUZZER_VERSION}")
246247
ExternalProject_Add(lief_libfuzzer
247248
SVN_REPOSITORY ${LIBFUZZER_URL}
248249
CONFIGURE_COMMAND ""

api/c/MachO/Parser.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,18 @@
2323
using namespace LIEF::MachO;
2424

2525
Macho_Binary_t** macho_parse(const char *file) {
26-
std::vector<Binary*> macho_binaries{Parser::parse(file)};
26+
FatBinary* macho_binaries = Parser::parse(file);
2727

2828
Macho_Binary_t** c_macho_binaries = static_cast<Macho_Binary_t**>(
29-
malloc((macho_binaries.size() + 1) * sizeof(Macho_Binary_t**)));
29+
malloc((macho_binaries->size() + 1) * sizeof(Macho_Binary_t**)));
3030

31-
for (size_t i = 0; i < macho_binaries.size(); ++i) {
32-
Binary* binary = macho_binaries [i];
31+
for (size_t i = 0; i < macho_binaries->size(); ++i) {
32+
Binary& binary = (*macho_binaries)[i];
3333
c_macho_binaries[i] = static_cast<Macho_Binary_t*>(malloc(sizeof(Macho_Binary_t)));
34-
init_c_binary(c_macho_binaries[i], binary);
34+
init_c_binary(c_macho_binaries[i], &binary);
3535
}
3636

37-
c_macho_binaries[macho_binaries.size()] = nullptr;
37+
c_macho_binaries[macho_binaries->size()] = nullptr;
3838

3939
return c_macho_binaries;
4040
}

api/python/MachO/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ set(LIEF_PYTHON_MACHO_SRC
22
"${CMAKE_CURRENT_LIST_DIR}/pyMachO.cpp"
33
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDylibCommand.cpp"
44
"${CMAKE_CURRENT_LIST_DIR}/objects/pyBinary.cpp"
5+
"${CMAKE_CURRENT_LIST_DIR}/objects/pyFatBinary.cpp"
56
"${CMAKE_CURRENT_LIST_DIR}/objects/pyLoadCommand.cpp"
67
"${CMAKE_CURRENT_LIST_DIR}/objects/pySegmentCommand.cpp"
78
"${CMAKE_CURRENT_LIST_DIR}/objects/pyHeader.cpp"
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/* Copyright 2017 R. Thomas
2+
* Copyright 2017 Quarkslab
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#include <algorithm>
17+
18+
#include "LIEF/MachO/FatBinary.hpp"
19+
20+
#include "pyMachO.hpp"
21+
22+
23+
void init_MachO_FatBinary_class(py::module& m) {
24+
25+
26+
py::class_<FatBinary>(m, "FatBinary")
27+
28+
.def_property_readonly("size",
29+
&FatBinary::size,
30+
"Number of " RST_CLASS_REF(lief.MachO.Binary) " registred")
31+
32+
.def("at",
33+
static_cast<Binary& (FatBinary::*)(size_t)>(&FatBinary::at),
34+
"Return the " RST_CLASS_REF(lief.MachO.Binary) " at the given index",
35+
"index"_a)
36+
37+
.def("__len__",
38+
&FatBinary::size)
39+
40+
41+
.def("__getitem__",
42+
static_cast<Binary& (FatBinary::*)(size_t)>(&FatBinary::operator[]),
43+
"",
44+
py::return_value_policy::reference)
45+
46+
.def("__iter__",
47+
static_cast<it_binaries (FatBinary::*)(void)>(&FatBinary::begin),
48+
py::return_value_policy::reference_internal)
49+
50+
.def("__str__",
51+
[] (const FatBinary& fat_binary)
52+
{
53+
std::ostringstream stream;
54+
stream << fat_binary;
55+
std::string str = stream.str();
56+
return str;
57+
});
58+
59+
}
60+

api/python/MachO/objects/pyParser.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ void init_MachO_Parser_class(py::module& m) {
2424

2525
// Parser (Parser)
2626
m.def("parse",
27-
static_cast<std::vector<Binary*> (*) (const std::string&)>(&LIEF::MachO::Parser::parse),
27+
static_cast<FatBinary* (*) (const std::string&)>(&LIEF::MachO::Parser::parse),
2828
"Parse the given binary and return a **list** of " RST_CLASS_REF(lief.MachO.Binary) " objects",
2929
"filename"_a,
3030
py::return_value_policy::take_ownership);
3131

3232

3333
m.def("parse",
34-
static_cast<std::vector<Binary*> (*) (const std::vector<uint8_t>&, const std::string&)>(&LIEF::MachO::Parser::parse),
34+
static_cast<FatBinary* (*) (const std::vector<uint8_t>&, const std::string&)>(&LIEF::MachO::Parser::parse),
3535
"Parse the given binary (from raw) and return a **list** of " RST_CLASS_REF(lief.MachO.Binary) " objects",
3636
py::arg("raw"), py::arg("name") = "",
3737
py::return_value_policy::take_ownership);

api/python/MachO/pyMachO.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,9 @@
2323
void init_MachO_module(py::module& m) {
2424
py::module LIEF_MachO_module = m.def_submodule("MachO", "Python API for MachO");
2525

26-
py::bind_vector<std::vector<Binary*>>(m, "macho_list");
27-
2826
// Objects
2927
init_MachO_Parser_class(LIEF_MachO_module);
28+
init_MachO_FatBinary_class(LIEF_MachO_module);
3029
init_MachO_Binary_class(LIEF_MachO_module);
3130
init_MachO_Header_class(LIEF_MachO_module);
3231
init_MachO_LoadCommand_class(LIEF_MachO_module);

api/python/MachO/pyMachO.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ using namespace LIEF::MachO;
2727
PYBIND11_MAKE_OPAQUE(std::vector<Binary*>)
2828

2929
void init_MachO_Parser_class(py::module&);
30+
void init_MachO_FatBinary_class(py::module&);
3031
void init_MachO_Binary_class(py::module&);
3132
void init_MachO_Header_class(py::module&);
3233
void init_MachO_LoadCommand_class(py::module&);

api/python/pyIterators.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ void init_LIEF_iterators(py::module& m) {
6363
// MachO
6464
// =====
6565
#if defined(LIEF_MACHO_MODULE)
66+
init_ref_iterator<LIEF::MachO::it_binaries>(m);
6667
init_ref_iterator<LIEF::MachO::it_relocations>(m);
6768
init_ref_iterator<LIEF::MachO::it_commands>(m);
6869
init_ref_iterator<LIEF::MachO::it_symbols>(m);

doc/sphinx/api/cpp/macho.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ Parsers
1313

1414
----------
1515

16+
FatBinary
17+
*********
18+
19+
.. doxygenclass:: LIEF::MachO::FatBinary
20+
:project: lief
21+
22+
----------
23+
1624
Binary
1725
******
1826

doc/sphinx/api/python/macho.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,17 @@ Parser
1010

1111
----------
1212

13+
FatBinary
14+
*********
15+
16+
.. autoclass:: lief.MachO.FatBinary
17+
:members:
18+
:inherited-members:
19+
:undoc-members:
20+
21+
----------
22+
23+
1324
.. _python-macho-binary-api-ref:
1425

1526
Binary

0 commit comments

Comments
 (0)