Skip to content

Commit 736195a

Browse files
committed
input validation: add overflow checks to library interfaces
also adds according tests for the C interface
1 parent 1ce3b2f commit 736195a

3 files changed

Lines changed: 81 additions & 13 deletions

File tree

include/lib_helper_functions.h

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#pragma once
2828

2929
#include <chrono>
30+
#include <limits>
3031
#include <string>
3132
#include <sstream>
3233
#include <type_traits>
@@ -133,6 +134,17 @@ bool is_compatible(mt_kahypar_partitioned_hypergraph_t partitioned_hg, mt_kahypa
133134
return false;
134135
}
135136

137+
template<typename OutType, typename InType>
138+
void check_overflow(const InType& value, const char* what) {
139+
if (value > static_cast<InType>(std::numeric_limits<OutType>::max())) {
140+
std::string msg = std::string(what) + " overflows input range of internal data type: " + STR(value);
141+
if constexpr (sizeof(OutType) < 8) {
142+
msg += " (build with -DKAHYPAR_USE_64_BIT_IDS=ON to support larger ID ranges)";
143+
}
144+
throw InvalidInputException(msg);
145+
}
146+
}
147+
136148
void check_if_all_relevant_parameters_are_set(Context& context) {
137149
bool success = true;
138150
auto check_parameter = [&](bool is_uninitialized, const char* warning_msg) {
@@ -302,6 +314,9 @@ mt_kahypar_hypergraph_t create_hypergraph(const Context& context,
302314
const vec<vec<HypernodeID>>& edge_vector,
303315
const mt_kahypar_hyperedge_weight_t* hyperedge_weights,
304316
const mt_kahypar_hypernode_weight_t* vertex_weights) {
317+
check_overflow<HypernodeID>(num_vertices, "number of vertices");
318+
check_overflow<HyperedgeID>(num_hyperedges, "number of hyperedges");
319+
305320
switch ( context.partition.preset_type ) {
306321
case PresetType::deterministic:
307322
case PresetType::deterministic_quality:
@@ -327,9 +342,11 @@ mt_kahypar_hypergraph_t create_hypergraph_from_adjacency_array(const Context& co
327342
const mt_kahypar_hypernode_id_t num_vertices,
328343
const mt_kahypar_hyperedge_id_t num_hyperedges,
329344
const size_t* hyperedge_indices,
330-
const mt_kahypar_hyperedge_id_t* hyperedges,
345+
const mt_kahypar_hypernode_id_t* hyperedges,
331346
const mt_kahypar_hyperedge_weight_t* hyperedge_weights,
332347
const mt_kahypar_hypernode_weight_t* vertex_weights) {
348+
check_overflow<HypernodeID>(num_vertices, "number of vertices");
349+
check_overflow<HyperedgeID>(num_hyperedges, "number of hyperedges");
333350
if (hyperedge_indices[0] != 0) {
334351
throw InvalidInputException("First entry in hyperedge indices must be 0, but is: " + STR(hyperedge_indices[0]));
335352
}
@@ -350,7 +367,9 @@ mt_kahypar_hypergraph_t create_hypergraph_from_adjacency_array(const Context& co
350367
const size_t num_pins = hyperedge_indices[he + 1] - hyperedge_indices[he];
351368
edge_vector[he].resize(num_pins);
352369
for ( size_t i = 0; i < num_pins; ++i ) {
353-
edge_vector[he][i] = hyperedges[hyperedge_indices[he] + i];
370+
mt_kahypar_hypernode_id_t pin = hyperedges[hyperedge_indices[he] + i];
371+
check_overflow<HypernodeID>(pin, "pin");
372+
edge_vector[he][i] = pin;
354373
}
355374

356375
utils::deduplicateHyperedgePins(edge_vector[he], num_duplicated_pins, num_hes_with_duplicated_pins);
@@ -368,6 +387,9 @@ mt_kahypar_hypergraph_t create_graph(const Context& context,
368387
const vec<std::pair<HypernodeID, HypernodeID>>& edge_vector,
369388
const mt_kahypar_hyperedge_weight_t* edge_weights,
370389
const mt_kahypar_hypernode_weight_t* vertex_weights) {
390+
check_overflow<HypernodeID>(num_vertices, "number of nodes");
391+
check_overflow<HyperedgeID>(num_edges, "number of edges");
392+
371393
switch ( context.partition.preset_type ) {
372394
case PresetType::deterministic:
373395
case PresetType::deterministic_quality:

lib/mtkahypar.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,12 +336,14 @@ mt_kahypar_hypergraph_t mt_kahypar_create_graph(const mt_kahypar_context_t* cont
336336
mt_kahypar_error_t* error) {
337337
// Transform adjacence array into adjacence list
338338
vec<std::pair<mt_kahypar::HypernodeID, mt_kahypar::HypernodeID>> edge_vector(num_edges);
339-
tbb::parallel_for<mt_kahypar::HyperedgeID>(0, num_edges, [&](const mt_kahypar::HyperedgeID& he) {
340-
edge_vector[he] = std::make_pair(edges[2*he], edges[2*he + 1]);
341-
});
342339

343340
const Context& c = *reinterpret_cast<const Context*>(context);
344341
try {
342+
tbb::parallel_for<mt_kahypar::HyperedgeID>(0, num_edges, [&](const mt_kahypar::HyperedgeID& he) {
343+
lib::check_overflow<HypernodeID>(edges[2*he], "endpoint of edge");
344+
lib::check_overflow<HypernodeID>(edges[2*he + 1], "endpoint of edge");
345+
edge_vector[he] = std::make_pair(edges[2*he], edges[2*he + 1]);
346+
});
345347
return lib::create_graph(c, num_vertices, num_edges, edge_vector, edge_weights, vertex_weights);
346348
} catch ( std::exception& ex ) {
347349
*error = to_error(ex);

tests/interface/interface_test.cc

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ namespace mt_kahypar {
167167
TEST(MtKaHyPar, StaticHypergraphConstructionHandlesErrors) {
168168
mt_kahypar_error_t error;
169169
mt_kahypar_context_t* context = mt_kahypar_context_from_preset(DEFAULT);
170-
const mt_kahypar_hypernode_id_t num_vertices = 7;
171-
const mt_kahypar_hyperedge_id_t num_hyperedges = 4;
170+
mt_kahypar_hypernode_id_t num_vertices = 7;
171+
mt_kahypar_hyperedge_id_t num_hyperedges = 4;
172172

173173
std::unique_ptr<size_t[]> hyperedge_indices = std::make_unique<size_t[]>(5);
174174
hyperedge_indices[0] = 0; hyperedge_indices[1] = 2; hyperedge_indices[2] = 6;
@@ -210,6 +210,21 @@ namespace mt_kahypar {
210210
attempt_construction("giant HE");
211211
hyperedge_indices[4] = 12;
212212

213+
hyperedges[3] = static_cast<mt_kahypar_hypernode_id_t>(std::numeric_limits<HypernodeID>::max()) + 1;
214+
attempt_construction("overflow pin");
215+
hyperedges[3] = 1;
216+
217+
hyperedge_indices[4] = static_cast<mt_kahypar_hypernode_id_t>(std::numeric_limits<HypernodeID>::max()) + 13;
218+
attempt_construction("overflow HE index");
219+
hyperedge_indices[4] = 12;
220+
221+
num_vertices = static_cast<mt_kahypar_hypernode_id_t>(std::numeric_limits<HypernodeID>::max()) + 8;
222+
attempt_construction("overflow num vertices");
223+
num_vertices = 7;
224+
225+
num_hyperedges = static_cast<mt_kahypar_hyperedge_id_t>(std::numeric_limits<HyperedgeID>::max()) + 5;
226+
attempt_construction("overflow num hyperedges");
227+
213228
mt_kahypar_free_hypergraph(hypergraph);
214229
}
215230

@@ -245,8 +260,8 @@ namespace mt_kahypar {
245260
TEST(MtKaHyPar, DynamicHypergraphConstructionHandlesErrors) {
246261
mt_kahypar_error_t error;
247262
mt_kahypar_context_t* context = mt_kahypar_context_from_preset(HIGHEST_QUALITY);
248-
const mt_kahypar_hypernode_id_t num_vertices = 7;
249-
const mt_kahypar_hyperedge_id_t num_hyperedges = 4;
263+
mt_kahypar_hypernode_id_t num_vertices = 7;
264+
mt_kahypar_hyperedge_id_t num_hyperedges = 4;
250265

251266
std::unique_ptr<size_t[]> hyperedge_indices = std::make_unique<size_t[]>(5);
252267
hyperedge_indices[0] = 0; hyperedge_indices[1] = 2; hyperedge_indices[2] = 6;
@@ -288,6 +303,21 @@ namespace mt_kahypar {
288303
attempt_construction("giant HE");
289304
hyperedge_indices[4] = 12;
290305

306+
hyperedges[3] = static_cast<mt_kahypar_hypernode_id_t>(std::numeric_limits<HypernodeID>::max()) + 1;
307+
attempt_construction("overflow pin");
308+
hyperedges[3] = 1;
309+
310+
hyperedge_indices[4] = static_cast<mt_kahypar_hypernode_id_t>(std::numeric_limits<HypernodeID>::max()) + 13;
311+
attempt_construction("overflow HE index");
312+
hyperedge_indices[4] = 12;
313+
314+
num_vertices = static_cast<mt_kahypar_hypernode_id_t>(std::numeric_limits<HypernodeID>::max()) + 8;
315+
attempt_construction("overflow num vertices");
316+
num_vertices = 7;
317+
318+
num_vertices = static_cast<mt_kahypar_hyperedge_id_t>(std::numeric_limits<HyperedgeID>::max()) + 5;
319+
attempt_construction("overflow num hyperedges");
320+
291321
mt_kahypar_free_hypergraph(hypergraph);
292322
}
293323

@@ -320,8 +350,8 @@ namespace mt_kahypar {
320350
TEST(MtKaHyPar, StaticGraphConstructionHandlesErrors) {
321351
mt_kahypar_error_t error;
322352
mt_kahypar_context_t* context = mt_kahypar_context_from_preset(DEFAULT);
323-
const mt_kahypar_hypernode_id_t num_vertices = 5;
324-
const mt_kahypar_hyperedge_id_t num_hyperedges = 6;
353+
mt_kahypar_hypernode_id_t num_vertices = 5;
354+
mt_kahypar_hyperedge_id_t num_hyperedges = 6;
325355

326356
std::unique_ptr<mt_kahypar_hypernode_id_t[]> edges =
327357
std::make_unique<mt_kahypar_hypernode_id_t[]>(12);
@@ -347,6 +377,13 @@ namespace mt_kahypar {
347377
edges[2] = 2;
348378
attempt_construction("self loop");
349379

380+
edges[2] = static_cast<mt_kahypar_hypernode_id_t>(std::numeric_limits<HypernodeID>::max()) + 1;
381+
attempt_construction("overflow node ID");
382+
edges[2] = 0;
383+
384+
num_vertices = static_cast<mt_kahypar_hypernode_id_t>(std::numeric_limits<HypernodeID>::max()) + 6;
385+
attempt_construction("overflow num nodes");
386+
350387
mt_kahypar_free_hypergraph(graph);
351388
}
352389

@@ -379,8 +416,8 @@ namespace mt_kahypar {
379416
TEST(MtKaHyPar, DynamicGraphConstructionHandlesErrors) {
380417
mt_kahypar_error_t error;
381418
mt_kahypar_context_t* context = mt_kahypar_context_from_preset(HIGHEST_QUALITY);
382-
const mt_kahypar_hypernode_id_t num_vertices = 5;
383-
const mt_kahypar_hyperedge_id_t num_hyperedges = 6;
419+
mt_kahypar_hypernode_id_t num_vertices = 5;
420+
mt_kahypar_hyperedge_id_t num_hyperedges = 6;
384421

385422
std::unique_ptr<mt_kahypar_hypernode_id_t[]> edges =
386423
std::make_unique<mt_kahypar_hypernode_id_t[]>(12);
@@ -406,6 +443,13 @@ namespace mt_kahypar {
406443
edges[2] = 2;
407444
attempt_construction("self loop");
408445

446+
edges[2] = static_cast<mt_kahypar_hypernode_id_t>(std::numeric_limits<HypernodeID>::max()) + 1;
447+
attempt_construction("overflow node ID");
448+
edges[2] = 0;
449+
450+
num_vertices = static_cast<mt_kahypar_hypernode_id_t>(std::numeric_limits<HypernodeID>::max()) + 6;
451+
attempt_construction("overflow num nodes");
452+
409453
mt_kahypar_free_hypergraph(graph);
410454
}
411455

0 commit comments

Comments
 (0)