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);