diff --git a/reader/flow_graph.cc b/reader/flow_graph.cc
index b1156cbb..829e35e6 100644
--- a/reader/flow_graph.cc
+++ b/reader/flow_graph.cc
@@ -26,11 +26,14 @@
#include "third_party/absl/log/check.h"
#include "third_party/absl/log/log.h"
#include "third_party/absl/memory/memory.h"
-#include "third_party/absl/strings/ascii.h"
+#include "third_party/absl/status/status.h"
+#include "third_party/absl/strings/str_cat.h"
#include "third_party/absl/types/optional.h"
#include "third_party/zynamics/binexport/architectures.h"
+#include "third_party/absl/strings/ascii.h"
#include "third_party/zynamics/binexport/reader/graph_utility.h"
#include "third_party/zynamics/binexport/reader/instruction.h"
+#include "third_party/zynamics/binexport/util/status_macros.h"
#include "third_party/zynamics/binexport/util/types.h"
namespace security::binexport {
@@ -76,7 +79,7 @@ uint32_t GetEdgeTypeFromProto(BinExport2::FlowGraph::Edge::Type type) {
}
}
-void EdgesFromEdgeProto(
+absl::Status EdgesFromEdgeProto(
const BinExport2& proto, const BinExport2::FlowGraph& flow_graph_proto,
const std::vector
& addresses,
const std::vector& instruction_addresses,
@@ -84,6 +87,18 @@ void EdgesFromEdgeProto(
FlowGraph::Graph::edges_size_type>>* edges,
std::vector* edge_properties) {
for (const auto& edge : flow_graph_proto.edge()) {
+ if (edge.source_basic_block_index() < 0 ||
+ edge.source_basic_block_index() >= proto.basic_block_size() ||
+ edge.target_basic_block_index() < 0 ||
+ edge.target_basic_block_index() >= proto.basic_block_size()) {
+ return absl::InvalidArgumentError(absl::StrCat(
+ "Found an invalid binexport proto for binary: ",
+ proto.meta_information().executable_id(),
+ " - invalid basic block index inside the flow graph - source basic "
+ "block index: ",
+ edge.source_basic_block_index(),
+ " target basic block index: ", edge.target_basic_block_index()));
+ }
const Address source_address =
instruction_addresses[proto.basic_block(edge.source_basic_block_index())
.instruction_index(0)
@@ -107,6 +122,7 @@ void EdgesFromEdgeProto(
edge_properties->push_back(edge_property);
}
}
+ return absl::OkStatus();
}
void AssignVertexProperties(
@@ -144,9 +160,28 @@ FlowGraph::Vertex FlowGraph::GetVertex(Address address) const {
}
std::unique_ptr FlowGraph::FromBinExport2Proto(
+ const BinExport2& proto, const BinExport2::FlowGraph& flow_graph_proto,
+ const std::vector& instruction_addresses) {
+ auto flow_graph =
+ FromBinExport2(proto, flow_graph_proto, instruction_addresses);
+ if (!flow_graph.ok()) {
+ LOG(FATAL) << "Failed to create flow graph: " << flow_graph.status();
+ return nullptr;
+ }
+ return std::move(flow_graph.value());
+}
+
+absl::StatusOr> FlowGraph::FromBinExport2(
const BinExport2& proto, const BinExport2::FlowGraph& flow_graph_proto,
const std::vector& instruction_addresses) {
auto flow_graph = absl::make_unique();
+ if (flow_graph_proto.entry_basic_block_index() < 0 ||
+ flow_graph_proto.entry_basic_block_index() >= proto.basic_block_size()) {
+ return absl::InvalidArgumentError(absl::StrCat(
+ "Invalid entry basic block for binary: ",
+ proto.meta_information().executable_id(),
+ " - entry bb index: ", flow_graph_proto.entry_basic_block_index()));
+ }
int entry_instruction_index =
proto.basic_block(flow_graph_proto.entry_basic_block_index())
.instruction_index(0)
@@ -160,6 +195,15 @@ std::unique_ptr FlowGraph::FromBinExport2Proto(
addresses.reserve(flow_graph_proto.basic_block_index_size());
for (int basic_block_index : flow_graph_proto.basic_block_index()) {
+ if (basic_block_index < 0 ||
+ basic_block_index >= proto.basic_block_size()) {
+ return absl::InvalidArgumentError(
+ absl::StrCat("Found an invalid binexport proto for binary: ",
+ proto.meta_information().executable_id(),
+ " - invalid basic block index inside the flow graph - "
+ "basic block index: ",
+ basic_block_index));
+ }
const BinExport2::BasicBlock& basic_block_proto(
proto.basic_block(basic_block_index));
VertexProperty vertex_property;
@@ -202,8 +246,9 @@ std::unique_ptr FlowGraph::FromBinExport2Proto(
edges.reserve(flow_graph_proto.edge_size());
std::vector edge_properties;
edge_properties.reserve(flow_graph_proto.edge_size());
- EdgesFromEdgeProto(proto, flow_graph_proto, addresses, instruction_addresses,
- &edges, &edge_properties);
+ NA_RETURN_IF_ERROR(EdgesFromEdgeProto(proto, flow_graph_proto, addresses,
+ instruction_addresses, &edges,
+ &edge_properties));
flow_graph->graph_ = Graph(boost::edges_are_unsorted_multi_pass,
edges.begin(), edges.end(), addresses.size());
flow_graph->architecture_ = GetSupportedArchitecture(proto);
diff --git a/reader/flow_graph.h b/reader/flow_graph.h
index 75fed1dc..e3d71685 100644
--- a/reader/flow_graph.h
+++ b/reader/flow_graph.h
@@ -20,12 +20,15 @@
#include //NOLINT
#include // NOLINT
+#include
#include
+#include
#include
+#include
#include
#include
-#include "third_party/absl/base/macros.h"
+#include "third_party/absl/base/attributes.h"
#include "third_party/absl/types/optional.h"
#include "third_party/zynamics/binexport/architectures.h"
#include "third_party/zynamics/binexport/binexport2.pb.h"
@@ -85,6 +88,11 @@ class FlowGraph {
VertexProperty, EdgeProperty>;
// Factory method to read and initialize a flow graph (BinExport2).
+ static absl::StatusOr> FromBinExport2(
+ const BinExport2& proto, const BinExport2::FlowGraph& flow_graph_proto,
+ const std::vector& instruction_addresses);
+
+ ABSL_DEPRECATED("Use FromBinExport2Proto that returns a StatusOr instead.")
static std::unique_ptr FromBinExport2Proto(
const BinExport2& proto, const BinExport2::FlowGraph& flow_graph_proto,
const std::vector& instruction_addresses);